From 9d45348c95e16da0f94bb4332f68f1478b5d4a86 Mon Sep 17 00:00:00 2001 From: leiyun Date: Mon, 1 Mar 2021 19:41:17 +0800 Subject: [PATCH] sdk 2.0 --- app/build.gradle | 33 +- app/libs/wenote.jar | Bin 14269 -> 13559 bytes app/src/main/AndroidManifest.xml | 4 + .../java/com/yzx/webebook/MainActivity.kt | 6 + .../yzx/webebook/activity/BookActivity.java | 128 ++-- .../yzx/webebook/activity/Main1Activity.java | 725 ++++++++++++++++++ .../com/yzx/webebook/activity/NoteActivity.kt | 139 ++-- .../com/yzx/webebook/utils/AppInstance.java | 16 + .../com/yzx/webebook/utils/FileUtils.java | 192 +++++ .../com/yzx/webebook/utils/GsonHelper.java | 58 ++ .../com/yzx/webebook/utils/ListUtils.java | 204 +++++ .../com/yzx/webebook/utils/StringUtils.java | 332 ++++++++ .../main/jniLibs/armeabi/libpaintworker.so | 1 - app/src/main/res/layout/activity_main.xml | 10 +- app/src/main/res/layout/activity_main1.xml | 120 +++ buildKey/wenote.jks | Bin 0 -> 2379 bytes buildKey/wetao_app_key | Bin 0 -> 2223 bytes 17 files changed, 1839 insertions(+), 129 deletions(-) create mode 100644 app/src/main/java/com/yzx/webebook/activity/Main1Activity.java create mode 100644 app/src/main/java/com/yzx/webebook/utils/AppInstance.java create mode 100644 app/src/main/java/com/yzx/webebook/utils/FileUtils.java create mode 100644 app/src/main/java/com/yzx/webebook/utils/GsonHelper.java create mode 100644 app/src/main/java/com/yzx/webebook/utils/ListUtils.java create mode 100644 app/src/main/java/com/yzx/webebook/utils/StringUtils.java delete mode 100644 app/src/main/jniLibs/armeabi/libpaintworker.so create mode 100644 app/src/main/res/layout/activity_main1.xml create mode 100644 buildKey/wenote.jks create mode 100644 buildKey/wetao_app_key diff --git a/app/build.gradle b/app/build.gradle index d60b187..7cfca14 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,9 +6,9 @@ apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 30 - buildToolsVersion "31.0.0 rc1" + buildToolsVersion "30.0.3" defaultConfig { - applicationId "com.yzx.webebook" + applicationId "com.yzx1.webebook" minSdkVersion 26 targetSdkVersion 30 versionCode 2 @@ -23,16 +23,30 @@ android { storePassword KEY_PWD v2SigningEnabled false } + release { + storeFile file("../buildKey/wenote.jks") + keyAlias 'wetao' + keyPassword 'lhb@123' + storePassword 'lhb@123' + v2SigningEnabled false + } + debug { + storeFile file("../buildKey/wenote.jks") + keyAlias 'wetao' + keyPassword 'lhb@123' + storePassword 'lhb@123' + v2SigningEnabled false + } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - zipAlignEnabled true - debuggable false - signingConfig signingConfigs.yzx +// zipAlignEnabled true +// debuggable false + signingConfig signingConfigs.release // 移除无用的resource文件 - shrinkResources false +// shrinkResources false } debug { @@ -52,6 +66,13 @@ android { } } } + + lintOptions { + checkReleaseBuilds false + // Or, if you prefer, you can continue to check for errors in release builds, + // but continue the build even when errors are found: + abortOnError false + } } dependencies { diff --git a/app/libs/wenote.jar b/app/libs/wenote.jar index 527a62160722b2024bb931fbab0df8a708f791b9..746e5b220630277527eeeadeb7f61c029ab1de36 100644 GIT binary patch literal 13559 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 Dmw0(9 literal 14269 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 + + >() { NoteActivity.active(this, "测试笔记写字", json,1) } + btn7.setOnClickListener { + startActivity() + } + /*OkGo.post("https://fileupload.oa.qbjjyyun.net/edufile/fileUpload") .tag(this) .params("token","0fc58a8df03c46d3f85b1047c4693cf6") diff --git a/app/src/main/java/com/yzx/webebook/activity/BookActivity.java b/app/src/main/java/com/yzx/webebook/activity/BookActivity.java index de916fe..a4bd4dc 100644 --- a/app/src/main/java/com/yzx/webebook/activity/BookActivity.java +++ b/app/src/main/java/com/yzx/webebook/activity/BookActivity.java @@ -41,6 +41,7 @@ import com.lzy.okgo.OkGo; import com.lzy.okgo.callback.StringCallback; import com.lzy.okgo.model.Response; import com.wetao.note.NotePageInfo; +import com.wetao.note.OnInitedListener; import com.wetao.note.WeNoteView; import com.wetao.note.WePoint; import com.yzx.webebook.R; @@ -101,8 +102,8 @@ public class BookActivity extends Activity { private Button mPenWidthSubBtn; private Button mEraserWidthBtn; private Button mCancelBtn; - private CheckBox mCBEraser; - private CheckBox mCBStrokes; +// private CheckBox mCBEraser; +// private CheckBox mCBStrokes; private TextView mPenBtn; private TextView mRubberBtn; @@ -137,7 +138,7 @@ public class BookActivity extends Activity { } Log.d(TAG, "Flash test : ++++++++ mView.getHeight() = " + mView.getHeight() + ", count = " + count); //mView.initNative(new Rect(mScreenW, mScreenH - mView.getHeight(), 0, mScreenH), SAVE_PIC_PATH); - mView.initNative(new Rect(mScreenW, mScreenH - mView.getHeight(), 0, mScreenH)); +// mView.initNative(new Rect(mScreenW, mScreenH - mView.getHeight(), 0, mScreenH)); mView.setTouchEventHander(mPointHandler); Log.d(TAG, "Flash test : ++++++ mRunnable() start loader notepageinfo"); @@ -194,6 +195,16 @@ public class BookActivity extends Activity { } } + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (hasFocus) { + mView.onResume(); + } else { + mView.onPause(); + } + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -230,7 +241,7 @@ public class BookActivity extends Activity { mView.setEnable(false); mBGId++; if (mBGId >= mBGDrawableList.length) mBGId = 0; - mView.updateBackground(mBGDrawableList[mBGId]); + mView.setBackgroundResource(mBGDrawableList[mBGId]); mPicBtn.setText("背景" + mBGId); saveBGId(); } @@ -325,36 +336,9 @@ public class BookActivity extends Activity { } }); - mCBEraser = (CheckBox) findViewById(R.id.eraser); - mCBEraser.setSelected(false); - mCBEraser.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (mView.isEraserEnable()) { - mCBEraser.setSelected(false); - mView.setEraserEnable(false); - } else { - mCBEraser.setSelected(true); - mView.setEraserEnable(true); - } - } - }); + //mCBEraser.setVisibility(View.GONE); - mCBStrokes = (CheckBox) findViewById(R.id.strokes); - mCBStrokes.setSelected(false); - mCBStrokes.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (mView.isStrokesEnable()) { - mCBStrokes.setSelected(false); - mView.setStrokesEnable(false); - } else { - mCBStrokes.setSelected(true); - mView.setStrokesEnable(true); - } - } - }); mWePointList = new ArrayList(); mWePointList.clear(); @@ -367,14 +351,24 @@ public class BookActivity extends Activity { mHandler = new Handler(); // mHandler.postDelayed(mRunnable, 1000); + mView.setOnFinishListener(new OnInitedListener() { + @Override + public void onInited() { + mView.post(new Runnable() { + @Override + public void run() { + mHandler.post(mRunnable); + } + }); + } - mView.post(new Runnable() { @Override - public void run() { - mHandler.post(mRunnable); + public void onSizeChanged() { + } }); + IntentFilter filter = new IntentFilter(); filter.addAction(SCREEN_ON); filter.addAction(SCREEN_OFF); @@ -384,10 +378,10 @@ public class BookActivity extends Activity { mPenBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if(mView.isEraserEnable()){ - mView.setEraserEnable(false); - mPenBtn.setCompoundDrawablesWithIntrinsicBounds(0,R.mipmap.ic_book_pen_select,0,0); - mRubberBtn.setCompoundDrawablesWithIntrinsicBounds(0,R.mipmap.ic_book_rubber,0,0); + if (mView.getPenType() == WeNoteView.TYPE_DRAW_ERASER) { + mView.setPenType(WeNoteView.TYPE_DRAW_CURVE); + mPenBtn.setCompoundDrawablesWithIntrinsicBounds(0, R.mipmap.ic_book_pen_select, 0, 0); + mRubberBtn.setCompoundDrawablesWithIntrinsicBounds(0, R.mipmap.ic_book_rubber, 0, 0); } } }); @@ -396,10 +390,10 @@ public class BookActivity extends Activity { mRubberBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if(!mView.isEraserEnable()){ - mView.setEraserEnable(true); - mPenBtn.setCompoundDrawablesWithIntrinsicBounds(0,R.mipmap.ic_book_pen,0,0); - mRubberBtn.setCompoundDrawablesWithIntrinsicBounds(0,R.mipmap.ic_book_rubber_select,0,0); + if (mView.getPenType() != WeNoteView.TYPE_DRAW_ERASER) { + mView.setPenType(WeNoteView.TYPE_DRAW_ERASER); + mPenBtn.setCompoundDrawablesWithIntrinsicBounds(0, R.mipmap.ic_book_pen, 0, 0); + mRubberBtn.setCompoundDrawablesWithIntrinsicBounds(0, R.mipmap.ic_book_rubber_select, 0, 0); } } }); @@ -413,11 +407,11 @@ public class BookActivity extends Activity { mPenWidthBtn.setText("+宽度5"); mPenWidthSubBtn.setText("-宽度5"); //橡皮擦 - mCBEraser.setSelected(false); - mView.setEraserEnable(false); +// mCBEraser.setSelected(false); + mView.setPenType(WeNoteView.TYPE_DRAW_CURVE); + mView.updateEnableStatus(); //笔锋 - mCBStrokes.setSelected(false); - mView.setStrokesEnable(false); +// mCBStrokes.setSelected(false); //橡皮擦 mView.setEraserWidth(20); mEraserWidthBtn.setText("橡皮宽20"); @@ -660,21 +654,21 @@ public class BookActivity extends Activity { } Log.d(TAG, "Flash test : +++++ loadOldPage() mNotePageInfo = " + mNotePageInfo); mBGId = mNotePageInfo.drwId; - mView.showExistPage(mNotePageInfo.notePath, mBGDrawableList[mBGId]); + mView.showExistPage(mNotePageInfo.notePath); + mView.setBackgroundResource(mBGDrawableList[mBGId]); mPicBtn.setText("背景" + mBGId); } public void onResume() { Log.d(TAG, "Flash test : +++++++ onResume()"); - mView.setEnable(true); - mView.setSleepMode(true); + mView.onResume(); mReDrawEnable = true; super.onResume(); } public void onPause() { Log.d(TAG, "Flash test : +++++++ onPause()"); - mView.setEnable(false); + mView.onPause(); mReDrawEnable = false; super.onPause(); } @@ -683,7 +677,7 @@ public class BookActivity extends Activity { Log.d(TAG, "Flash test : +++++++ onDestroy()"); //mView.exitView(); mHandler.removeCallbacks(mRunnable); - mView.exitNative(); + mView.exitView(); if (mReceiver != null) { mContext.unregisterReceiver(mReceiver); mReceiver = null; @@ -717,11 +711,11 @@ public class BookActivity extends Activity { }; private void cancel(boolean save) { - mView.exitNativeOnly(); + mView.exitView(); if (save && mView.isHandwritingExist()) { saveNote(); } - mView.exit(); + mView.exitView(); BookActivity.this.finish(); } @@ -943,7 +937,7 @@ public class BookActivity extends Activity { public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { //to-do - mView.exitNative(); + mView.exitView(); if (mReceiver != null) { mContext.unregisterReceiver(mReceiver); mReceiver = null; @@ -1004,18 +998,18 @@ public class BookActivity extends Activity { @Override public void onReceive(Context context, Intent intent) { // 屏幕唤醒 - if (SCREEN_ON.equals(intent.getAction())) { - Log.e(TAG, "Flash test : ++++++ " + SCREEN_ON); - /*if (mDialog != null && mDialog.isShowing()) { - mView.setEnable(false); - }*/ - mView.setSleepMode(true); - } - // 屏幕休眠 - else if (SCREEN_OFF.equals(intent.getAction())) { - Log.e(TAG, "Flash test : ++++++ " + SCREEN_OFF); - mView.setSleepMode(true); - } +// if (SCREEN_ON.equals(intent.getAction())) { +// Log.e(TAG, "Flash test : ++++++ " + SCREEN_ON); +// /*if (mDialog != null && mDialog.isShowing()) { +// mView.setEnable(false); +// }*/ +// mView.setSleepMode(true); +// } +// // 屏幕休眠 +// else if (SCREEN_OFF.equals(intent.getAction())) { +// Log.e(TAG, "Flash test : ++++++ " + SCREEN_OFF); +// mView.setSleepMode(true); +// } } }; diff --git a/app/src/main/java/com/yzx/webebook/activity/Main1Activity.java b/app/src/main/java/com/yzx/webebook/activity/Main1Activity.java new file mode 100644 index 0000000..3dbde8a --- /dev/null +++ b/app/src/main/java/com/yzx/webebook/activity/Main1Activity.java @@ -0,0 +1,725 @@ +package com.yzx.webebook.activity; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.yzx.webebook.utils.FileUtils; +import com.yzx.webebook.utils.GsonHelper; +import com.yzx.webebook.utils.ListUtils; +import com.wetao.note.NotePageInfo; +import com.wetao.note.OnInitedListener; +import com.wetao.note.WeNoteView; +import com.wetao.note.WePoint; +import com.yzx.webebook.R; + +import android.Manifest; +import android.app.Activity; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.RelativeLayout; + + +public class Main1Activity extends Activity { + private static final String TAG = "MainActivity"; + + private static final String NOTE1_FOLDER_DIR = "/mnt/sdcard/MyTestNote/Note/"; + + static final int[] mBGDrawableList = {-1, R.drawable.background1, R.drawable.background2, + R.drawable.background3, R.drawable.background4, R.drawable.background5, R.drawable.background6, + R.drawable.background7, R.drawable.background8, R.drawable.background9, R.drawable.background10}; + + private static final int MSG_SAVE_END = 2001; + + private WeNoteView mView; + + private Button mDeleteBtn; + private Button mPicBtn; + private Button mClearBtn; + private Button mZoomBtn; + private Button mUndoBtn; + private Button mRedoBtn; + private Button mPenWidthBtn; + private Button mEraserWidthBtn; + private Button mCancelBtn; + private Button mTypeBtn; + + private CheckBox mVisibleCB; + + private static int mBGId = 0; + + private boolean mReDrawEnable = false; + + private static ArrayList mWePointList = null; + + private static NotePageInfo mNotePageInfo = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.activity_main1); + checkPermission(); + Log.d(TAG, "Flash test : +++++++ onCreate()"); + + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + + mView = findViewById(R.id.note_view); + mView.setBackground(null); + mBGId = 0; + + mDeleteBtn = findViewById(R.id.delete); + mDeleteBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (deleteNote(NOTE1_FOLDER_DIR)) { + cancel(false); + Main1Activity.this.finish(); + } + } + }); + + mPicBtn = findViewById(R.id.init); + mPicBtn.setText("背景" + mBGId); + mPicBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mBGId++; + if (mBGId >= mBGDrawableList.length) mBGId = 0; + if (mBGId == 0) { + mView.setBackground(new ColorDrawable()); + mPicBtn.setText("背景0"); + } else { + mView.setBackgroundResource(mBGDrawableList[mBGId]); + mPicBtn.setText("背景" + mBGId); + } + saveBGId(NOTE1_FOLDER_DIR, mBGId); + } + }); + + mClearBtn = findViewById(R.id.clear); + mClearBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mView.clear(); + } + }); + + mPenWidthBtn = findViewById(R.id.pen_width); + mPenWidthBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int width = mView.getPenWidth(); + if (width == 10) { + width = 1; + } else { + width++; + } + + if (width > 0 && width <= 10) { + mView.setPenWidth(width); + mPenWidthBtn.setText("宽度" + width); + } + } + }); + + mZoomBtn = findViewById(R.id.zoom); + mZoomBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mView.getLayoutParams(); + // 设置宽为100dp + params.width = 1000; + // 设置高为100dp + params.height = 200; + // 根据布局参数的设置,重新设置view(这里用了text view,当然其他的view也是通用的)的大小 + mView.setLayoutParams(params); + } + }); + + mUndoBtn = findViewById(R.id.undo); + mUndoBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mView.unDo(); + } + }); + + mRedoBtn = findViewById(R.id.redo); + mRedoBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mView.reDo(); + } + }); + + mEraserWidthBtn = findViewById(R.id.eraser_width); + mEraserWidthBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int width = mView.getEraserWidth(); + if (width == 20) { + width = 1; + } else { + width++; + } + + if (width > 0 && width <= 20) { + mView.setEraserWidth(width); + mEraserWidthBtn.setText("橡皮宽" + width); + } + } + }); + + mCancelBtn = findViewById(R.id.cancel); + mCancelBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + cancel(true); + Main1Activity.this.finish(); + } + }); + + mTypeBtn = findViewById(R.id.draw_circle); + mTypeBtn.setTypeface(null, Typeface.BOLD); + mTypeBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int type = mView.getPenType(); + Log.d(TAG, "Flash test : +++++++ onClick() type btn current type = " + type); + if (type == WeNoteView.TYPE_DRAW_CURVE) { + setPenType(WeNoteView.TYPE_DRAW_STROKES); + mTypeBtn.setText("笔锋"); + } else if (type == WeNoteView.TYPE_DRAW_STROKES) { + setPenType(WeNoteView.TYPE_DRAW_LINE); + mTypeBtn.setText("直线"); + } else if (type == WeNoteView.TYPE_DRAW_LINE) { + setPenType(WeNoteView.TYPE_DRAW_TRIANGLE); + mTypeBtn.setText("三角形"); + } else if (type == WeNoteView.TYPE_DRAW_TRIANGLE) { + setPenType(WeNoteView.TYPE_DRAW_CIRCLE); + mTypeBtn.setText("圆形"); + } else if (type == WeNoteView.TYPE_DRAW_CIRCLE) { + setPenType(WeNoteView.TYPE_DRAW_RECT); + mTypeBtn.setText("矩形"); + } else if (type == WeNoteView.TYPE_DRAW_RECT) { + setPenType(WeNoteView.TYPE_DRAW_ERASER); + mTypeBtn.setText("橡皮擦"); + } else if (type == WeNoteView.TYPE_DRAW_ERASER) { + setPenType(WeNoteView.TYPE_DRAW_CIRCLE_ERASER); + mTypeBtn.setText("圈涂"); + } else if (type == WeNoteView.TYPE_DRAW_CIRCLE_ERASER) { + setPenType(WeNoteView.TYPE_DRAW_CURVE); + mTypeBtn.setText("曲线"); + } + + } + }); + + mVisibleCB = findViewById(R.id.visible); + mVisibleCB.setSelected(true); + mVisibleCB.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mVisibleCB.isChecked()) { + mVisibleCB.setSelected(false); + mView.setVisibility(View.INVISIBLE); + } else { + mVisibleCB.setSelected(true); + mView.setVisibility(View.VISIBLE); + } + } + }); + + mWePointList = new ArrayList(); + mWePointList.clear(); + + mView.setOnFinishListener(new OnInitedListener() { + @Override + public void onInited() { + //mView.setTouchEventHander(mPointHandler); + + Log.d(TAG, "Flash test : ++++++ mRunnable() start loader notepageinfo"); + if (mNotePageInfo == null) { + mNotePageInfo = getNotePageInfo(NOTE1_FOLDER_DIR); + } + if (mNotePageInfo == null) { + Log.d(TAG, "Flash test : +++++ no note, so init a page"); + initPage(NOTE1_FOLDER_DIR, 0, mBGId); + } + loadOldPage(); + } + + @Override + public void onSizeChanged() { + + } + }); + + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + Log.d(TAG, "Flash test : ++++++++++ onWindowFocusChanged() hasFocus = " + hasFocus); + if (hasFocus) { + mView.onResume(); + mReDrawEnable = true; + } else { + mView.onPause(); + mReDrawEnable = false; + } + } + + private void setPenType(int type) { + mView.setPenType(type); + mView.updateEnableStatus(); + } + + private void loadOldPage() { + if (mNotePageInfo == null) { + return; + } + Log.d(TAG, "Flash test : +++++ loadOldPage() mNotePageInfo = " + mNotePageInfo); + mBGId = mNotePageInfo.drwId; + if (mBGDrawableList[mBGId] == -1) { + mView.setBackground(new ColorDrawable()); + } else { + mView.setBackgroundResource(mBGDrawableList[mBGId]); + } + mView.showExistPage(mNotePageInfo.notePath); + mPicBtn.setText("背景" + mBGId); + } + + public void onResume() { + Log.d(TAG, "Flash test : +++++++ onResume()"); + //mView.setEnable(true); + mView.onResume(); + mReDrawEnable = true; + super.onResume(); + } + + public void onPause() { + Log.d(TAG, "Flash test : +++++++ onPause()"); + mView.onPause(); + mReDrawEnable = false; + super.onPause(); + } + + public void onDestroy() { + Log.d(TAG, "Flash test : +++++++ onDestroy()"); + mView.exitView(); + super.onDestroy(); +// System.exit(0); + } + + private Handler mPointHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + int what = msg.what; + //同步获取的笔记点坐标信息msg + if (what == WeNoteView.TOUCH_EVENT) { + WePoint point = (WePoint) msg.obj; + Log.d(TAG, "Flash test : ++++++++ mPointHandler WePoint = " + point); + mWePointList.add(point); + transData(point); + } + + //保存笔记结束msg + if (what == MSG_SAVE_END) { + int status = msg.arg1; + if (status > 0) { //保存成功 + Log.d(TAG, "Flash test : ++++++++ mPointHandler page save ok"); + //Toast.makeText(mContext, "Note saved OK", Toast.LENGTH_SHORT).show(); + } else { //保存失败 + Log.d(TAG, "Flash test : ++++++++ mPointHandler page save failed"); + //Toast.makeText(mContext, "Note saved Fail", Toast.LENGTH_SHORT).show(); + } + } + } + }; + + private void cancel(boolean save) { + if (save && mView.isHandwritingExist()) { + saveNote(NOTE1_FOLDER_DIR, mView, mBGId); + } + Main1Activity.this.finish(); + } + + private boolean initPage(String dir, int viewId, int bgId) { + Log.d(TAG, "Flash test : +++++++++ intPage()"); + File file = new File(dir); + if(!file.exists()) { + Log.e(TAG, "Flash test : +++++++++ addPageFolder() no folder path = " + dir); + if (!makeDir(file)) { + return false; + } + } + + String notePath = null; + file = new File(dir + "/note.png"); + if(file.exists()) { + notePath = dir + "/note.png"; + } + file = new File(dir + "/.drawable.txt"); + if(!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + } + if (bgId == 1) bgId = 2; + saveBGId(dir, bgId); + mNotePageInfo = new NotePageInfo(notePath, bgId); + return true; + } + + private boolean deleteNote(String dir) { + Log.d(TAG, "Flash test : +++++++++ deletdNote()"); + File file = new File(dir); + if(!file.exists()) { + Log.e(TAG, "Flash test : +++++++++ deletdPageFolder() no folder path = " + dir); + return true; + } + deleteDirWithFile(file); + return true; + } + + private boolean saveNote(String dir, WeNoteView view, int bgId) { + Log.d(TAG, "Flash test : ++++++++ saveNote()"); + File f = new File(dir); + if(!f.exists()) { + Log.d(TAG, "Flash test : +++++++ saveNote() create folder " + dir); + if (!makeDir(f)) { + return false; + } + } + + String noteName = "note.png"; + final Bitmap bmp = Bitmap.createBitmap(view.getCurrentNoteBitmap()); + if (bmp == null) { + Log.e(TAG, "Flash test : ++++ saveNote() getCurrentNoteBitmap is null"); + return false; + } + + String path = dir + "/" + noteName; + if (!saveNoteWithoutBG(path, bmp)) { + Log.e(TAG, "Flash test : ++++ saveNote() saveNoteWithoutBG fail"); + freeBitmap(bmp); + return false; + } + + saveBGId(dir, bgId); + freeBitmap(bmp); + Log.e(TAG, "Flash test : ++++ saveNote() OK !!!!!"); + return true; + } + + private static boolean saveBGId(String dir, int bgId) { + Log.d(TAG, "Flash test : ++++++++ saveBGId drwId = " + bgId); + File f = new File(dir); + if(!f.exists()) { + Log.d(TAG, "Flash test : +++++++ saveAllNote() create folder " + dir); + if (!makeDir(f)) { + return false; + } + } + + String path = dir + "/.drawable.txt"; + writeFileData(path, String.valueOf(bgId)); + return true; + } + + private static void freeBitmap(Bitmap bit) { + if (bit != null && !bit.isRecycled()) { + bit.recycle(); + } + } + + + + //保存不带背景的笔记为png + private boolean saveNoteWithoutBG(String picPath, Bitmap bmp) { + Log.d(TAG, "Flash test : +++++++ saveNoteWithoutBG() picPath = " + picPath); + File f = new File(picPath); + if(f.exists()) { + f.delete(); + } + FileOutputStream fos = null; + try { + fos = new FileOutputStream(f); + bmp.compress(Bitmap.CompressFormat.PNG, 90, fos); + try { + fos.flush(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + try { + fos.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return true; + } + + //保存带背景的笔记为png + private boolean saveAll(String picPath, Bitmap bmp, Drawable drw) { + Log.d(TAG, "Flash test : ++++ saveAll() picPath = " + picPath); + int width = bmp.getWidth(); + int height = bmp.getHeight(); + + Bitmap bitmap = Bitmap.createBitmap(width, height, + drw.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); + Canvas canvas = new Canvas(bitmap); + drw.setBounds(0, 0, width, height); + drw.draw(canvas); + + canvas.drawBitmap(bmp, new Rect(0, 0, width, height), + new Rect(0, 0, width, height) , null); + canvas.save();//Canvas.ALL_SAVE_FLAG); + canvas.restore(); + + boolean result = saveNoteWithoutBG(picPath, bitmap); + if (bitmap != null && !bitmap.isRecycled()) { + bitmap.recycle(); + bitmap = null; + } + System.gc(); + return result; + } + + //保存笔记背景为png + private boolean saveNoteBG(String picPath, Drawable drw, int width, int height) { + Log.d(TAG, "Flash test : ++++ saveNoteBG() picPath = " + picPath); + Bitmap bitmap = Bitmap.createBitmap(width, height, + drw.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); + Canvas canvas = new Canvas(bitmap); + drw.setBounds(0, 0, width, height); + drw.draw(canvas); + + boolean result = saveNoteWithoutBG(picPath, bitmap); + if (bitmap != null && !bitmap.isRecycled()) { + bitmap.recycle(); + bitmap = null; + } + System.gc(); + return result; + } + + //重绘之前绘制的画笔 + private void drawWePointList() { + if (mView.isReDrawDoing()) { + Log.i(TAG, "Flash test : +++++ drawWePointList() return because isReDrawDoing is true"); + return; + } + if (mWePointList != null && !mWePointList.isEmpty()) { + new Thread(new Runnable() { + @Override + public void run() { + mView.setReDrawEnable(true); + mReDrawEnable = true; + int size = mWePointList.size(); + int i = 0; + while (i= 23) { + if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + //如果没有写sd卡权限 + isGranted = false; + } + if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + isGranted = false; + } + Log.i("cbs","isGranted == "+isGranted); + if (!isGranted) { + this.requestPermissions( + new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission + .ACCESS_FINE_LOCATION, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE}, + 102); + } + } + } + + private static boolean makeDir(File folder) { + try { + //按照指定的路径创建文件夹 + folder.mkdirs(); + } catch (Exception e) { + // TODO: handle exception + Log.e(TAG, "Flash test : +++++ makeDir() create dir " + folder.getPath() + " error = " + e); + return false; + } + Log.d(TAG, "Flash test : +++++ makeDir() create dir " + folder.getPath()); + return true; + } + + private void deleteDirWithFile(File dir) { + if (dir == null || !dir.exists() || !dir.isDirectory()) + return; + for (File file : dir.listFiles()) { + if (file.isFile()) + file.delete(); // 删除所有文件 + else if (file.isDirectory()) + deleteDirWithFile(file); // 递规的方式删除文件夹 + } + dir.delete();// 删除目录本身 + } + + public static void writeFileData(String fileName, String content) { + File file = new File(fileName); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + try { + BufferedWriter bw = new BufferedWriter(new FileWriter(file)); + bw.write(content); + bw.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + //打开指定文件,读取其数据,返回字符串对象 + public static String readFileData(String fileName) { + File file = new File(fileName); + if (!file.exists()) { + return "1"; + } + BufferedReader br; + try { + br = new BufferedReader(new FileReader(file)); + //System.out.println("br.readLine=" + br.readLine()); + return br.readLine(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return "1"; + } + + private List stringList; + private void transData(WePoint point) { + if (ListUtils.isEmpty(stringList)) { + stringList = new ArrayList<>(); + } + String s = GsonHelper.toJson(point); + stringList.add(s); + stringList.add("\r\n"); + if (point.action == MotionEvent.ACTION_UP) { + String join = String.join("", stringList); + saveData(join); + stringList.clear(); + } + } + + private void saveData(String msg) { + File file = new File("/mnt/sdcard/point.txt"); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + FileUtils.writeFile(file.getPath(), msg, true); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yzx/webebook/activity/NoteActivity.kt b/app/src/main/java/com/yzx/webebook/activity/NoteActivity.kt index c975029..5404dca 100644 --- a/app/src/main/java/com/yzx/webebook/activity/NoteActivity.kt +++ b/app/src/main/java/com/yzx/webebook/activity/NoteActivity.kt @@ -32,6 +32,7 @@ import com.lzy.okgo.OkGo import com.lzy.okgo.callback.StringCallback import com.lzy.okgo.model.Response import com.wetao.note.NotePageInfo +import com.wetao.note.OnInitedListener import com.wetao.note.WeNoteView import com.wetao.note.WePoint import com.yzx.webebook.R @@ -104,12 +105,11 @@ class NoteActivity : BaseActivity>() { //背景 new_init.setOnClickListener { - note_view.setEnable(false) mBgId++ if (mBgId >= mBGDrawableList.size) { mBgId = 0 } - note_view.updateBackground(mBGDrawableList[mBgId]) + note_view.setBackgroundResource(mBGDrawableList[mBgId]) val note = notList[currIndex] note.BGid = mBgId } @@ -119,8 +119,10 @@ class NoteActivity : BaseActivity>() { } //笔 pen.setOnClickListener { - if (note_view.isEraserEnable) { - note_view.isEraserEnable = false + if (note_view.penType == WeNoteView.TYPE_DRAW_ERASER) { + note_view.penType = WeNoteView.TYPE_DRAW_CURVE + note_view.updateEnableStatus() + Log.d(TAG, "initNoteView: ${note_view.penType}") pen.setCompoundDrawablesWithIntrinsicBounds( 0, R.mipmap.ic_book_pen_select, @@ -137,8 +139,10 @@ class NoteActivity : BaseActivity>() { } //橡皮 new_eraser.setOnClickListener { - if (!note_view.isEraserEnable) { - note_view.isEraserEnable = true + if (note_view.penType != WeNoteView.TYPE_DRAW_ERASER) { + note_view.penType = WeNoteView.TYPE_DRAW_ERASER + note_view.updateEnableStatus() + Log.d(TAG, "initNoteView: ${note_view.penType}") pen.setCompoundDrawablesWithIntrinsicBounds(0, R.mipmap.ic_book_pen, 0, 0) new_eraser.setCompoundDrawablesWithIntrinsicBounds( 0, @@ -150,7 +154,7 @@ class NoteActivity : BaseActivity>() { } //加纸 new_add.setOnClickListener { - val lastBGid = notList[notList.size-1].BGid + val lastBGid = notList[notList.size - 1].BGid val note = Note() note.BGid = lastBGid notList.add(note) @@ -210,6 +214,15 @@ class NoteActivity : BaseActivity>() { } } + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + if (hasFocus) { + note_view.onResume() + } else { + note_view.onPause() + } + } + @SuppressLint("SetTextI18n") override fun initData() { val json = intent.getStringExtra("note_info") @@ -235,11 +248,36 @@ class NoteActivity : BaseActivity>() { notList.add(Note()) } +// Log.d(TAG, "初始化开始note_view") +// note_view.post { +// Log.d(TAG, "初始化开始note_view.post") +// mHandler.post(mRunnable) +// } Log.d(TAG, "初始化开始note_view") - note_view.post { - Log.d(TAG, "初始化开始note_view.post") - mHandler.post(mRunnable) - } + note_view.setOnFinishListener(object : OnInitedListener { + override fun onSizeChanged() { + + } + + override fun onInited() { +// note_view.post { +// Log.d(TAG, "初始化开始note_view.post") +// mHandler.post(mRunnable) +// } + + + if (mNotePageInfo == null) { + mNotePageInfo = getNotePageInfo(NOTE_FOLDER_DIR) + } + if (mNotePageInfo == null) { + Log.d(TAG, "Flash test : +++++ no note, so init a page"); + initPage() + } + initNoteView() + loadImage(0) + } + + }) tv_page_index.text = "1/${notList.size}" indexBox.visibility = if (notList.size > 1) { @@ -251,7 +289,7 @@ class NoteActivity : BaseActivity>() { val canAddPage = intent.getIntExtra("can_add_page", 1) if (canAddPage == 1) { new_add.visibility = View.VISIBLE - }else{ + } else { new_add.visibility = View.GONE } } @@ -263,10 +301,8 @@ class NoteActivity : BaseActivity>() { val bgId = note.BGid if (TextUtils.isEmpty(key)) { note.key = Date().time.toString() - note_view.showExistPage( - "", - mBGDrawableList[bgId] - ) + note_view.showExistPage("") + note_view.setBackgroundResource(mBGDrawableList[bgId]) currKey = note.key currIndex = index mBgId = bgId @@ -279,10 +315,8 @@ class NoteActivity : BaseActivity>() { return } mBgId = bgId ?: 0 - note_view.showExistPage( - path, - mBGDrawableList[mBgId] - ) + note_view.showExistPage(path) + note_view.setBackgroundResource(mBGDrawableList[bgId]) currKey = key currIndex = index @@ -312,10 +346,8 @@ class NoteActivity : BaseActivity>() { return } mBgId = bgId ?: 0 - note_view.showExistPage( - path, - mBGDrawableList[mBgId] - ) + note_view.showExistPage(path) + note_view.setBackgroundResource(mBGDrawableList[bgId]) currKey = key currIndex = index @@ -334,10 +366,8 @@ class NoteActivity : BaseActivity>() { .into(customTarget) } else { note.key = Date().time.toString() - note_view.showExistPage( - "", - mBGDrawableList[bgId] - ) + note_view.showExistPage("") + note_view.setBackgroundResource(mBGDrawableList[bgId]) currKey = note.key currIndex = index mBgId = bgId ?: 0 @@ -468,20 +498,19 @@ class NoteActivity : BaseActivity>() { } override fun onResume() { - note_view.setEnable(true) - note_view.setSleepMode(true) + note_view.onResume() super.onResume() } override fun onPause() { - note_view.setEnable(false) + note_view.onPause() super.onPause() } override fun onDestroy() { //mView.exitView(); mHandler.removeCallbacks(mRunnable) - note_view.exitNative() + note_view.exitView() if (mReceiver != null) { unregisterReceiver(mReceiver) mReceiver = null @@ -491,7 +520,7 @@ class NoteActivity : BaseActivity>() { override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_BACK) { - note_view.exitNative() + note_view.exitView() if (mReceiver != null) { unregisterReceiver(mReceiver) mReceiver = null @@ -504,14 +533,15 @@ class NoteActivity : BaseActivity>() { val SCREEN_ON = "android.intent.action.SCREEN_ON" val SCREEN_OFF = "android.intent.action.SCREEN_OFF" + private var mReceiver: BroadcastReceiver? = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { // 屏幕唤醒 - if (SCREEN_ON == intent.action) { - note_view.setSleepMode(true) - } else if (SCREEN_OFF == intent.action) { - note_view.setSleepMode(true) - } +// if (SCREEN_ON == intent.action) { +// note_view.setSleepMode(true) +// } else if (SCREEN_OFF == intent.action) { +// note_view.setSleepMode(true) +// } } } @@ -536,14 +566,14 @@ class NoteActivity : BaseActivity>() { TAG, "Flash test : ++++++++ mView.getHeight() = " + note_view.height + ", count = " + count ); - note_view.initNative( - Rect( - mScreenW, - mScreenH - note_view.height, - 0, - mScreenH - ) - ) +// note_view.initNative( +// Rect( +// mScreenW, +// mScreenH - note_view.height, +// 0, +// mScreenH +// ) +// ) note_view.setTouchEventHander(mPointHandler) Log.d(TAG, "Flash test : ++++++ mRunnable() start loader notepageinfo"); if (mNotePageInfo == null) { @@ -562,14 +592,17 @@ class NoteActivity : BaseActivity>() { private fun initNoteView() { //写字板初始化 - note_view.background = null +// note_view.setEnable(true) note_view.penWidth = 3 - note_view.isEraserEnable = false + note_view.penType = WeNoteView.TYPE_DRAW_STROKES note_view.eraserWidth = 20 + note_view.updateEnableStatus() + + Log.d(TAG, "initNoteView: ${note_view.penType}") } override fun finish() { - note_view.exitNative() + note_view.exitView() if (mReceiver != null) { unregisterReceiver(mReceiver) mReceiver = null @@ -578,7 +611,7 @@ class NoteActivity : BaseActivity>() { } override fun onBackPressed() { - note_view.exitNative() + note_view.exitView() if (mReceiver != null) { unregisterReceiver(mReceiver) mReceiver = null @@ -607,10 +640,8 @@ class NoteActivity : BaseActivity>() { return } mBgId = mNotePageInfo?.drwId ?: 0 - note_view.showExistPage( - mNotePageInfo?.notePath, - mBGDrawableList[mBgId] - ) + note_view.showExistPage(mNotePageInfo?.notePath) + note_view.setBackgroundResource(mBGDrawableList[mBgId]) } //从笔记文件夹中读取当前笔记的页面信息 diff --git a/app/src/main/java/com/yzx/webebook/utils/AppInstance.java b/app/src/main/java/com/yzx/webebook/utils/AppInstance.java new file mode 100644 index 0000000..2a0bad5 --- /dev/null +++ b/app/src/main/java/com/yzx/webebook/utils/AppInstance.java @@ -0,0 +1,16 @@ +package com.yzx.webebook.utils; + +import android.app.Application; + +public class AppInstance { + + private static Application sApplication; + + public static void init(Application application) { + sApplication = application; + } + + public static Application get() { + return sApplication; + } +} diff --git a/app/src/main/java/com/yzx/webebook/utils/FileUtils.java b/app/src/main/java/com/yzx/webebook/utils/FileUtils.java new file mode 100644 index 0000000..fc33244 --- /dev/null +++ b/app/src/main/java/com/yzx/webebook/utils/FileUtils.java @@ -0,0 +1,192 @@ +package com.yzx.webebook.utils; + +import android.content.Context; + +import com.wetao.note.WePoint; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.ArrayList; + +/** + * Used 获取SD卡根目录、读写文件、移动、复制、删除文件、获取文件名、后缀名操作类(需要MyApplication中的getAppContext()方法) + * + * @author andrew 2015-9-2 + */ +@SuppressWarnings("deprecation") +public class FileUtils { + private static final String TAG = "FileUtils"; + + /** + * read file to string list, a element of list is a line + * + * @param filePath + * @param charsetName The name of a supported {@link java.nio.charset.Charset charset} + * @return if file not exist, return null, else return content of file + * @throws RuntimeException if an error occurs while operator BufferedReader + */ + public static ArrayList readFileToList(String filePath, String charsetName) { + File file = new File(filePath); + ArrayList fileContent = new ArrayList(); + if (file == null || !file.isFile()) { + return null; + } + + BufferedReader reader = null; + try { + InputStreamReader is = new InputStreamReader(new FileInputStream(file), charsetName); + reader = new BufferedReader(is); + String line = null; + while ((line = reader.readLine()) != null) { + WePoint wePoint = GsonHelper.fromJson(line, WePoint.class); + if (wePoint == null) continue; + fileContent.add(wePoint); + } + reader.close(); + return fileContent; + } catch (IOException e) { + throw new RuntimeException("Flash test : +++++++++ IOException occurred. ", e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + throw new RuntimeException("Flash test : +++++++++ IOException occurred. ", e); + } + } + } + } + + public static ArrayList readAssetsFileToList(Context cxt, String filePath) { + ArrayList fileContent = new ArrayList(); + BufferedReader reader = null; + try { + InputStreamReader is = new InputStreamReader(cxt.getAssets().open(filePath), "utf-8"); + reader = new BufferedReader(is); + String line = null; + while ((line = reader.readLine()) != null) { + WePoint wePoint = GsonHelper.fromJson(line, WePoint.class); + if (wePoint == null) continue; + fileContent.add(wePoint); + } + reader.close(); + return fileContent; + } catch (IOException e) { + throw new RuntimeException("Flash test : +++++++++ IOException occurred. ", e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + throw new RuntimeException("Flash test : +++++++++ IOException occurred. ", e); + } + } + } + + } + + /** + * write file【写文件:字符串】 + * + * @param filePath + * @param content + * @param append is append, if true, write to the end of file, else clear content of file and write into it + * @return return false if content is empty, true otherwise + * @throws RuntimeException if an error occurs while operator FileWriter + */ + public static boolean writeFile(String filePath, String content, boolean append) { + //字符串判空 + if (StringUtils.isEmpty(content)) { + return false; + } + + FileWriter fileWriter = null; + try { + makeDirs(filePath); + fileWriter = new FileWriter(filePath, append); + fileWriter.write(content); + fileWriter.close(); + //updateGallery(filePath);//媒体库数据更新 + return true; + } catch (IOException e) { + throw new RuntimeException("IOException occurred. ", e); + } finally { + if (fileWriter != null) { + try { + fileWriter.close(); + } catch (IOException e) { + throw new RuntimeException("IOException occurred. ", e); + } + } + } + } + + + /** + * write file + * + * @param file the file to be opened for writing. + * @param stream the input stream + * @param append if true, then bytes will be written to the end of the file rather than the beginning + * @return return true + * @throws RuntimeException if an error occurs while operator FileOutputStream + */ + public static boolean writeFile(File file, InputStream stream, boolean append) { + OutputStream o = null; + try { + makeDirs(file.getAbsolutePath()); + if (!file.exists()) file.createNewFile(); + o = new FileOutputStream(file, append); + byte data[] = new byte[1024]; + int length = -1; + while ((length = stream.read(data)) != -1) { + o.write(data, 0, length); + } + o.flush(); + //updateGallery(file.getAbsolutePath());//媒体库数据更新 + return true; + } catch (FileNotFoundException e) { + throw new RuntimeException("FileNotFoundException occurred. ", e); + } catch (IOException e) { + throw new RuntimeException("IOException occurred. ", e); + } finally { + if (o != null) { + try { + o.close(); + stream.close(); + } catch (IOException e) { + throw new RuntimeException("IOException occurred. ", e); + } + } + } + } + + public static boolean makeDirs(String filePath) { + String folderName = getFolderName(filePath); + if (StringUtils.isEmpty(folderName)) { + return false; + } + + File folder = new File(folderName); + return (folder.exists() && folder.isDirectory()) ? true : folder.mkdirs(); + } + + public static String getFolderName(String filePath) { + + if (StringUtils.isEmpty(filePath)) { + return filePath; + } + + int filePosi = filePath.lastIndexOf(File.separator); + return (filePosi == -1) ? "" : filePath.substring(0, filePosi); + } + +} diff --git a/app/src/main/java/com/yzx/webebook/utils/GsonHelper.java b/app/src/main/java/com/yzx/webebook/utils/GsonHelper.java new file mode 100644 index 0000000..af7c90d --- /dev/null +++ b/app/src/main/java/com/yzx/webebook/utils/GsonHelper.java @@ -0,0 +1,58 @@ +package com.yzx.webebook.utils; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Created by andrew on 2016/8/15 0015. + */ +public class GsonHelper { + + public static String toJson(Object src){ + try { + return new Gson().toJson(src); + } catch (Exception e){ + e.printStackTrace(); + } + return null; + } + + public static T fromJson(String json, Class clazz) { + try { + return new Gson().fromJson(json, clazz); + } catch (Exception e){ + e.printStackTrace(); + } + return null; + } + + public static List fromJsonArray(String json, Class clazz) { + try { + List lst = new ArrayList(); + JsonArray array = new JsonParser().parse(json).getAsJsonArray(); + for(final JsonElement elem : array){ + lst.add(new Gson().fromJson(elem, clazz)); + } + return lst; + } catch (Exception e){ + e.printStackTrace(); + } + return null; + } + + public static T fromJsonObject(String json, Class clazz) { + try { + JsonElement elem = new JsonParser().parse(json).getAsJsonObject(); + return new Gson().fromJson(elem, clazz); + } catch (Exception e){ + e.printStackTrace(); + } + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yzx/webebook/utils/ListUtils.java b/app/src/main/java/com/yzx/webebook/utils/ListUtils.java new file mode 100644 index 0000000..7719fb5 --- /dev/null +++ b/app/src/main/java/com/yzx/webebook/utils/ListUtils.java @@ -0,0 +1,204 @@ +package com.yzx.webebook.utils; + +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * List Utils + * + * @author andrew 2015-9-2 + */ +public class ListUtils { + + /** default join separator **/ + public static final String DEFAULT_JOIN_SEPARATOR = ","; + + private ListUtils() { + throw new AssertionError(); + } + + /** + * get size of list + * + *

+     * getSize(null)   =   0;
+     * getSize({})     =   0;
+     * getSize({1})    =   1;
+     * 
+ * + * @param + * @param sourceList + * @return if list is null or empty, return 0, else return {@link List#size()}. + */ + public static int getSize(List sourceList) { + return sourceList == null ? 0 : sourceList.size(); + } + + /** + * is null or its size is 0 + * + *
+     * isEmpty(null)   =   true;
+     * isEmpty({})     =   true;
+     * isEmpty({1})    =   false;
+     * 
+ * + * @param + * @param sourceList + * @return if list is null or its size is 0, return true, else return false. + */ + public static boolean isEmpty(List sourceList) { + return (sourceList == null || sourceList.size() == 0); + } + + /** + * join list to string, separator is "," + * + *
+     * join(null)      =   "";
+     * join({})        =   "";
+     * join({a,b})     =   "a,b";
+     * 
+ * + * @param list + * @return join list to string, separator is ",". if list is empty, return "" + */ + public static String join(List list) { + return join(list, DEFAULT_JOIN_SEPARATOR); + } + + /** + * join list to string + * + *
+     * join(null, '#')     =   "";
+     * join({}, '#')       =   "";
+     * join({a,b,c}, ' ')  =   "abc";
+     * join({a,b,c}, '#')  =   "a#b#c";
+     * 
+ * + * @param list + * @param separator + * @return join list to string. if list is empty, return "" + */ + public static String join(List list, char separator) { + return join(list, new String(new char[] {separator})); + } + + /** + * join list to string. if separator is null, use {@link #DEFAULT_JOIN_SEPARATOR} + * + *
+     * join(null, "#")     =   "";
+     * join({}, "#$")      =   "";
+     * join({a,b,c}, null) =   "a,b,c";
+     * join({a,b,c}, "")   =   "abc";
+     * join({a,b,c}, "#")  =   "a#b#c";
+     * join({a,b,c}, "#$") =   "a#$b#$c";
+     * 
+ * + * @param list + * @param separator + * @return join list to string with separator. if list is empty, return "" + */ + public static String join(List list, String separator) { + return list == null ? "" : TextUtils.join(separator, list); + } + + /** + * add distinct entry to list + * + * @param + * @param sourceList + * @param entry + * @return if entry already exist in sourceList, return false, else add it and return true. + */ + public static boolean addDistinctEntry(List sourceList, V entry) { + return (sourceList != null && !sourceList.contains(entry)) ? sourceList.add(entry) : false; + } + + /** + * add all distinct entry to list1 from list2 + * + * @param + * @param sourceList + * @param entryList + * @return the count of entries be added + */ + public static int addDistinctList(List sourceList, List entryList) { + if (sourceList == null || isEmpty(entryList)) { + return 0; + } + + int sourceCount = sourceList.size(); + for (V entry : entryList) { + if (!sourceList.contains(entry)) { + sourceList.add(entry); + } + } + return sourceList.size() - sourceCount; + } + + /** + * remove duplicate entries in list + * + * @param + * @param sourceList + * @return the count of entries be removed + */ + public static int distinctList(List sourceList) { + if (isEmpty(sourceList)) { + return 0; + } + + int sourceCount = sourceList.size(); + int sourceListSize = sourceList.size(); + for (int i = 0; i < sourceListSize; i++) { + for (int j = (i + 1); j < sourceListSize; j++) { + if (sourceList.get(i).equals(sourceList.get(j))) { + sourceList.remove(j); + sourceListSize = sourceList.size(); + j--; + } + } + } + return sourceCount - sourceList.size(); + } + + /** + * add not null entry to list + * + * @param sourceList + * @param value + * @return
    + *
  • if sourceList is null, return false
  • + *
  • if value is null, return false
  • + *
  • return {@link List#add(Object)}
  • + *
+ */ + public static boolean addListNotNullValue(List sourceList, V value) { + return (sourceList != null && value != null) ? sourceList.add(value) : false; + } + + + /** + * invert list + * + * @param + * @param sourceList + * @return + */ + public static List invertList(List sourceList) { + if (isEmpty(sourceList)) { + return sourceList; + } + + List invertList = new ArrayList(sourceList.size()); + for (int i = sourceList.size() - 1; i >= 0; i--) { + invertList.add(sourceList.get(i)); + } + return invertList; + } +} diff --git a/app/src/main/java/com/yzx/webebook/utils/StringUtils.java b/app/src/main/java/com/yzx/webebook/utils/StringUtils.java new file mode 100644 index 0000000..e9793c5 --- /dev/null +++ b/app/src/main/java/com/yzx/webebook/utils/StringUtils.java @@ -0,0 +1,332 @@ +package com.yzx.webebook.utils; + +import android.text.TextUtils; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * String Utils + * + * @author andrew 2015-9-2 + */ +public class StringUtils { + + private StringUtils() { + throw new AssertionError(); + } + + /** + * is null or its length is 0 or it is made by space【字符串为空、长度为0、一个空格】 + * + *
+	 * isBlank(null) = true;
+	 * isBlank("") = true;
+	 * isBlank("  ") = true;
+	 * isBlank("a") = false;
+	 * isBlank("a ") = false;
+	 * isBlank(" a") = false;
+	 * isBlank("a b") = false;
+	 * 
+ * + * @param str + * @return if string is null or its size is 0 or it is made by space, return true, else return false. + */ + public static boolean isBlank(String str) { + return (str == null || str.trim().length() == 0); + } + + /** + * is null or its length is 0【字符串为空、长度为0】 + * + *
+	 * isEmpty(null) = true;
+	 * isEmpty("") = true;
+	 * isEmpty("  ") = false;
+	 * 
+ * + * @param str + * @return if string is null or its size is 0, return true, else return false. + */ + public static boolean isEmpty(CharSequence str) { + return (str == null || str.length() == 0); + } + + public static boolean isEqual(String paramString1, String paramString2) { + return paramString1.equals(paramString2); + } + + /** + * get length of CharSequence【字符串的长度】 + * + *
+	 * length(null) = 0;
+	 * length(\"\") = 0;
+	 * length(\"abc\") = 3;
+	 * 
+ * + * @param str + * @return if str is null or empty, return 0, else return {@link CharSequence#length()}. + */ + public static int length(CharSequence str) { + return str == null ? 0 : str.length(); + } + + /** + * null Object to empty string + * + *
+	 * nullStrToEmpty(null) = "";
+	 * nullStrToEmpty("") = "";
+	 * nullStrToEmpty("aa") = "aa";
+	 * 
+ * + * @param str + * @return + */ + public static String nullStrToEmpty(Object str) { + return (str == null ? "" : (str instanceof String ? (String)str : str.toString())); + } + + /** + * capitalize first letter + * + *
+	 * capitalizeFirstLetter(null)     =   null;
+	 * capitalizeFirstLetter("")       =   "";
+	 * capitalizeFirstLetter("2ab")    =   "2ab"
+	 * capitalizeFirstLetter("a")      =   "A"
+	 * capitalizeFirstLetter("ab")     =   "Ab"
+	 * capitalizeFirstLetter("Abc")    =   "Abc"
+	 * 
+ * + * @param str + * @return + */ + public static String capitalizeFirstLetter(String str) { + if (isEmpty(str)) { + return str; + } + + char c = str.charAt(0); + return (!Character.isLetter(c) || Character.isUpperCase(c)) ? str : new StringBuilder(str.length()) + .append(Character.toUpperCase(c)).append(str.substring(1)).toString(); + } + + /** + * encoded in utf-8 + * + *
+	 * utf8Encode(null)        =   null
+	 * utf8Encode("")          =   "";
+	 * utf8Encode("aa")        =   "aa";
+	 * utf8Encode("啊啊啊啊")   = "%E5%95%8A%E5%95%8A%E5%95%8A%E5%95%8A";
+	 * 
+ * + * @param str + * @return + * @throws UnsupportedEncodingException if an error occurs + */ + public static String utf8Encode(String str) { + if (!isEmpty(str) && str.getBytes().length != str.length()) { + try { + return URLEncoder.encode(str, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UnsupportedEncodingException occurred. ", e); + } + } + return str; + } + + /** + * encoded in utf-8, if exception, return defultReturn + * + * @param str + * @param defultReturn + * @return + */ + public static String utf8Encode(String str, String defultReturn) { + if (!isEmpty(str) && str.getBytes().length != str.length()) { + try { + return URLEncoder.encode(str, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return defultReturn; + } + } + return str; + } + + /** + * get innerHtml from href + * + *
+	 * getHrefInnerHtml(null)                                  = ""
+	 * getHrefInnerHtml("")                                    = ""
+	 * getHrefInnerHtml("mp3")                                 = "mp3";
+	 * getHrefInnerHtml("<a innerHtml</a>")                    = "<a innerHtml</a>";
+	 * getHrefInnerHtml("<a>innerHtml</a>")                    = "innerHtml";
+	 * getHrefInnerHtml("<a<a>innerHtml</a>")                    = "innerHtml";
+	 * getHrefInnerHtml("<a href="baidu.com">innerHtml</a>")               = "innerHtml";
+	 * getHrefInnerHtml("<a href="baidu.com" title="baidu">innerHtml</a>") = "innerHtml";
+	 * getHrefInnerHtml("   <a>innerHtml</a>  ")                           = "innerHtml";
+	 * getHrefInnerHtml("<a>innerHtml</a></a>")                      = "innerHtml";
+	 * getHrefInnerHtml("jack<a>innerHtml</a></a>")                  = "innerHtml";
+	 * getHrefInnerHtml("<a>innerHtml1</a><a>innerHtml2</a>")        = "innerHtml2";
+	 * 
+ * + * @param href + * @return
    + *
  • if href is null, return ""
  • + *
  • if not match regx, return source
  • + *
  • return the last string that match regx
  • + *
+ */ + public static String getHrefInnerHtml(String href) { + if (isEmpty(href)) { + return ""; + } + + String hrefReg = ".*<[\\s]*a[\\s]*.*>(.+?)<[\\s]*/a[\\s]*>.*"; + Pattern hrefPattern = Pattern.compile(hrefReg, Pattern.CASE_INSENSITIVE); + Matcher hrefMatcher = hrefPattern.matcher(href); + if (hrefMatcher.matches()) { + return hrefMatcher.group(1); + } + return href; + } + + /** + * process special char in html + * + *
+	 * htmlEscapeCharsToString(null) = null;
+	 * htmlEscapeCharsToString("") = "";
+	 * htmlEscapeCharsToString("mp3") = "mp3";
+	 * htmlEscapeCharsToString("mp3<") = "mp3<";
+	 * htmlEscapeCharsToString("mp3>") = "mp3\>";
+	 * htmlEscapeCharsToString("mp3&mp4") = "mp3&mp4";
+	 * htmlEscapeCharsToString("mp3"mp4") = "mp3\"mp4";
+	 * htmlEscapeCharsToString("mp3<>&"mp4") = "mp3\<\>&\"mp4";
+	 * 
+ * + * @param source + * @return + */ + public static String htmlEscapeCharsToString(String source) { + return StringUtils.isEmpty(source) ? source : source.replaceAll("<", "<").replaceAll(">", ">") + .replaceAll("&", "&").replaceAll(""", "\""); + } + + /** + * transform half width char to full width char + * + *
+	 * fullWidthToHalfWidth(null) = null;
+	 * fullWidthToHalfWidth("") = "";
+	 * fullWidthToHalfWidth(new String(new char[] {12288})) = " ";
+	 * fullWidthToHalfWidth("!"#$%&) = "!\"#$%&";
+	 * 
+ * + * @param s + * @return + */ + public static String fullWidthToHalfWidth(String s) { + if (isEmpty(s)) { + return s; + } + + char[] source = s.toCharArray(); + for (int i = 0; i < source.length; i++) { + if (source[i] == 12288) { + source[i] = ' '; + // } else if (source[i] == 12290) { + // source[i] = '.'; + } else if (source[i] >= 65281 && source[i] <= 65374) { + source[i] = (char)(source[i] - 65248); + } else { + source[i] = source[i]; + } + } + return new String(source); + } + + /** + * transform full width char to half width char + * + *
+	 * halfWidthToFullWidth(null) = null;
+	 * halfWidthToFullWidth("") = "";
+	 * halfWidthToFullWidth(" ") = new String(new char[] {12288});
+	 * halfWidthToFullWidth("!\"#$%&) = "!"#$%&";
+	 * 
+ * + * @param s + * @return + */ + public static String halfWidthToFullWidth(String s) { + if (isEmpty(s)) { + return s; + } + + char[] source = s.toCharArray(); + for (int i = 0; i < source.length; i++) { + if (source[i] == ' ') { + source[i] = (char)12288; + // } else if (source[i] == '.') { + // source[i] = (char)12290; + } else if (source[i] >= 33 && source[i] <= 126) { + source[i] = (char)(source[i] + 65248); + } else { + source[i] = source[i]; + } + } + return new String(source); + } + + private static String bytesToHexString(byte[] paramArrayOfByte) { + + StringBuilder localStringBuilder = new StringBuilder(); + for (int i = 0; i < paramArrayOfByte.length; i++) + { + String str = Integer.toHexString(0xFF & paramArrayOfByte[i]); + if (str.length() == 1) + localStringBuilder.append('0'); + localStringBuilder.append(str); + } + return localStringBuilder.toString(); + } + + public static String hashKey(String paramString) { + String localObject = ""; + if (!TextUtils.isEmpty(paramString)); + try + { + MessageDigest localMessageDigest = MessageDigest.getInstance("MD5"); + localMessageDigest.update(paramString.getBytes()); + String str = bytesToHexString(localMessageDigest.digest()); + localObject = str; + return localObject; + } + catch (NoSuchAlgorithmException localNoSuchAlgorithmException) + { + } + return String.valueOf(paramString.hashCode()); + } + + public static String stripLeadingSlash(String paramString) { + + if (TextUtils.isEmpty(paramString)) + { + return paramString; + } + int i = 0; + while (paramString.charAt(i) == '/'){ + i ++; + } + return paramString.substring(i); + } +} diff --git a/app/src/main/jniLibs/armeabi/libpaintworker.so b/app/src/main/jniLibs/armeabi/libpaintworker.so deleted file mode 100644 index 466849e..0000000 --- a/app/src/main/jniLibs/armeabi/libpaintworker.so +++ /dev/null @@ -1 +0,0 @@ -/system/lib/libpaintworker.so \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 49f57d0..24fa0c6 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -83,7 +83,15 @@ android:id="@+id/btn5" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="电子书页面(不带背景)" + android:text="电子书页面(笔记本)" + android:visibility="visible" + android:layout_marginTop="@dimen/d_20"/> + + diff --git a/app/src/main/res/layout/activity_main1.xml b/app/src/main/res/layout/activity_main1.xml new file mode 100644 index 0000000..ac49cc2 --- /dev/null +++ b/app/src/main/res/layout/activity_main1.xml @@ -0,0 +1,120 @@ + + + + +