diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml
index c0f43a2..e75312f 100644
--- a/.idea/assetWizardSettings.xml
+++ b/.idea/assetWizardSettings.xml
@@ -14,8 +14,8 @@
diff --git a/app/src/main/assets/updatelog.fy b/app/src/main/assets/updatelog.fy
index 2deae15..b02b6df 100644
--- a/app/src/main/assets/updatelog.fy
+++ b/app/src/main/assets/updatelog.fy
@@ -1,5 +1,13 @@
+2021.05.16
+风月读书v2.0.0
+更新内容:
+1、优化第三方书源(之前beta版本导入的第三方书源需要重新导入)
+2、修复已知bug
+3、新增崩溃日志记录
+4、关于界面新增崩溃日志分享
+
2021.05.15
-风月读书v1.9.8-beta
+风月读书v1.9.9-beta
更新内容:
1、修复搜索闪退的bug
diff --git a/app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java b/app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java
index 277d1d7..e9c2ecb 100644
--- a/app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java
+++ b/app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java
@@ -18,6 +18,8 @@ import androidx.annotation.NonNull;
import org.jetbrains.annotations.NotNull;
+import java.io.File;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
@@ -29,9 +31,14 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
+import io.reactivex.Observable;
+import io.reactivex.ObservableSource;
+import io.reactivex.functions.Function;
import xyz.fycz.myreader.common.APPCONST;
+import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.ui.activity.SplashActivity;
import xyz.fycz.myreader.util.utils.FileUtils;
+import xyz.fycz.myreader.util.utils.OkHttpUtils;
/**
* @author fengyue
@@ -40,6 +47,7 @@ import xyz.fycz.myreader.util.utils.FileUtils;
public final class CrashHandler implements Thread.UncaughtExceptionHandler {
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+
/**
* 注册 Crash 监听
*/
@@ -62,14 +70,11 @@ public final class CrashHandler implements Thread.UncaughtExceptionHandler {
@SuppressLint("ApplySharedPref")
@Override
public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
-
saveCrashLog(throwable);
-
// 不去触发系统的崩溃处理(com.android.internal.os.RuntimeInit$KillApplicationHandler)
if (mNextHandler != null && !mNextHandler.getClass().getName().startsWith("com.android.internal.os")) {
mNextHandler.uncaughtException(thread, throwable);
}
-
// 杀死进程(这个事应该是系统干的,但是它会多弹出一个崩溃对话框,所以需要我们自己手动杀死进程)
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
@@ -135,7 +140,8 @@ public final class CrashHandler implements Thread.UncaughtExceptionHandler {
String time = formatter.format(new Date());
String fileName = "crash-" + time + "-" + timestamp + ".log";
String path = APPCONST.LOG_DIR + fileName;
- FileUtils.writeText(mPhoneInfo + "\n\n" + mStackTrace, FileUtils.getFile(path));
+ File file = FileUtils.getFile(path);
+ FileUtils.writeText(mPhoneInfo + "\n\n" + mStackTrace, file);
}
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java b/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java
index 2aeacbd..2a307c1 100644
--- a/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java
+++ b/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java
@@ -21,6 +21,7 @@ public class URLCONST {
public static final String FY_READER_URL = "https://fyreader.fycz.tk";
public static final String AD_URL = FY_READER_URL + "/ad";
+ public static final String LOG_UPLOAD_URL = FY_READER_URL + "/logUpload";
public static final String DONATE = "https://gitee.com/fengyuecanzhu/Donate/raw/master";
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java
index c6bd143..979a87b 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java
@@ -8,15 +8,27 @@ import android.net.Uri;
import androidx.appcompat.widget.Toolbar;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableOnSubscribe;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.base.BaseActivity;
+import xyz.fycz.myreader.base.observer.MyObserver;
+import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.databinding.ActivityAboutBinding;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.util.ShareUtils;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.ToastUtils;
+import xyz.fycz.myreader.util.ZipUtils;
+import xyz.fycz.myreader.util.utils.FileUtils;
+import xyz.fycz.myreader.util.utils.OkHttpUtils;
+import xyz.fycz.myreader.util.utils.RxUtils;
/**
* @author fengyue
@@ -61,8 +73,9 @@ public class AboutActivity extends BaseActivity {
SharedPreUtils.getInstance().getString(getString(R.string.downloadLink), URLCONST.LAN_ZOUS_URL)));
binding.il.vwUpdate.setOnClickListener(v -> App.checkVersionByServer(this, true));
binding.il.vwUpdateLog.setOnClickListener(v -> DialogCreator.createAssetTipDialog(this, "更新日志", "updatelog.fy"));
+ binding.il.vwShareLog.setOnClickListener(v -> shareCrashLog());
binding.il.vwQq.setOnClickListener(v -> {
- if (!App.joinQQGroup(this,"8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn")){
+ if (!App.joinQQGroup(this, "8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn")) {
//数据
ClipData mClipData = ClipData.newPlainText("Label", "1085028304");
//把数据设置到剪切板上
@@ -73,7 +86,6 @@ public class AboutActivity extends BaseActivity {
});
binding.il.vwGit.setOnClickListener(v -> openIntent(Intent.ACTION_VIEW, getString(R.string.this_github_url)));
binding.il.vwDisclaimer.setOnClickListener(v -> DialogCreator.createAssetTipDialog(this, "免责声明", "disclaimer.fy"));
-
}
void openIntent(String intentName, String address) {
@@ -87,4 +99,65 @@ public class AboutActivity extends BaseActivity {
}
+ private void updateCrashLog() {
+ File logDir = new File(APPCONST.LOG_DIR);
+ if (!logDir.exists() || logDir.listFiles() == null || logDir.listFiles().length == 0) {
+ ToastUtils.showWarring("没有日志文件");
+ return;
+ }
+ Observable.create((ObservableOnSubscribe) emitter -> {
+ String time = String.valueOf(System.currentTimeMillis());
+ String fileName = "log-" + time + ".zip";
+ String logZip = FileUtils.getCachePath() + File.separator + fileName;
+ File zipFile = FileUtils.getFile(logZip);
+ if (ZipUtils.zipFile(logDir, zipFile)) {
+ emitter.onNext(OkHttpUtils.upload(URLCONST.LOG_UPLOAD_URL, logZip, fileName));
+ } else {
+ emitter.onError(new Throwable("日志文件压缩失败"));
+ }
+ emitter.onComplete();
+ }).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver() {
+ @Override
+ public void onNext(@NotNull String s) {
+ ToastUtils.showInfo(s);
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ ToastUtils.showError(e.getLocalizedMessage());
+ }
+
+ });
+ }
+
+ private void shareCrashLog() {
+ File logDir = new File(APPCONST.LOG_DIR);
+ if (!logDir.exists() || logDir.listFiles() == null || logDir.listFiles().length == 0) {
+ ToastUtils.showWarring("没有日志文件");
+ return;
+ }
+ Observable.create((ObservableOnSubscribe) emitter -> {
+ String time = String.valueOf(System.currentTimeMillis());
+ String fileName = "log-" + time + ".zip";
+ String logZip = FileUtils.getCachePath() + File.separator + fileName;
+ File zipFile = FileUtils.getFile(logZip);
+ if (ZipUtils.zipFile(logDir, zipFile)) {
+ emitter.onNext(zipFile);
+ } else {
+ emitter.onError(new Throwable("日志文件压缩失败"));
+ }
+ emitter.onComplete();
+ }).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver() {
+ @Override
+ public void onNext(@NotNull File file) {
+ ShareUtils.share(AboutActivity.this, file, file.getName(), "application/x-zip-compressed");
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ ToastUtils.showError(e.getLocalizedMessage());
+ }
+
+ });
+ }
}
diff --git a/app/src/main/java/xyz/fycz/myreader/util/OpenFileHelper.java b/app/src/main/java/xyz/fycz/myreader/util/OpenFileHelper.java
index 0d2a31f..7ad0752 100644
--- a/app/src/main/java/xyz/fycz/myreader/util/OpenFileHelper.java
+++ b/app/src/main/java/xyz/fycz/myreader/util/OpenFileHelper.java
@@ -6,9 +6,8 @@ import android.content.Intent;
import java.io.File;
-
public class OpenFileHelper {
- private final static String[][] MIME_MapTable={
+ private final static String[][] MIME_MapTable = {
//{后缀名,MIME类型}
{".3gp", "video/3gpp"},
{".apk", "application/vnd.android.package-archive"},
@@ -80,23 +79,24 @@ public class OpenFileHelper {
/**
* 打开文件
+ *
* @param file
*/
- public static void openFile(Context context,File file){
+ public static void openFile(Context context, File file) {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- //设置intent的Action属性
+ //设置intent的Action属性
intent.setAction(Intent.ACTION_VIEW);
- //获取文件file的MIME类型
+ //获取文件file的MIME类型
String type = getMIMEType(file);
- //设置intent的data和Type属性。
- intent.setDataAndType(/*uri*/UriFileUtil.getUriForFile(context,file), type);
- //跳转
+ //设置intent的data和Type属性。
+ intent.setDataAndType(/*uri*/UriFileUtil.getUriForFile(context, file), type);
+ //跳转
try {
context.startActivity(intent); //这里最好try一下,有可能会报错。 比如说你的MIME类型是打开邮箱,但是你手机里面没装邮箱客户端,就会报错。
- }catch (Exception e){
+ } catch (Exception e) {
e.printStackTrace();
ToastUtils.showError("没有安装相应的文件读取工具或者文件错误");
}
@@ -104,26 +104,26 @@ public class OpenFileHelper {
}
-
/**
* 根据文件后缀名获得对应的MIME类型。
+ *
* @param file
*/
private static String getMIMEType(File file) {
- String type="*/*";
+ String type = "*/*";
String fName = file.getName();
//获取后缀名前的分隔符"."在fName中的位置。
int dotIndex = fName.lastIndexOf(".");
- if(dotIndex < 0){
+ if (dotIndex < 0) {
return type;
}
-/* 获取文件的后缀名*/
- String end=fName.substring(dotIndex,fName.length()).toLowerCase();
- if(end=="")return type;
-//在MIME和文件类型的匹配表中找到对应的MIME类型。
- for(int i=0;i read finish", bodyStr);
return bodyStr;
}
}
@@ -180,7 +183,7 @@ public class OkHttpUtils {
String content = jsonObj.getString("content");
Document doc = Jsoup.parse(content);
content = doc.text();
- Log.d("Http: UpdateInfo", content);
+ Log.d("Http -> UpdateInfo", content);
return content;
}
}
@@ -322,4 +325,31 @@ public class OkHttpUtils {
this.content = content;
}
}
+
+
+ public static String upload(String url, String filePath, String fileName) throws IOException {
+ OkHttpClient client = getOkHttpClient();
+ RequestBody requestBody = new MultipartBody.Builder()
+ .setType(MultipartBody.FORM)
+ .addFormDataPart("file", fileName,
+ RequestBody.create(MediaType.parse("multipart/form-data"), new File(filePath)))
+ .build();
+
+ Request request = new Request.Builder()
+ .header("Authorization", "Client-ID " + UUID.randomUUID())
+ .url(url)
+ .post(requestBody)
+ .build();
+
+ Response response = client.newCall(request).execute();
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+ ResponseBody body = response.body();
+ if (body == null) {
+ return "";
+ } else {
+ String bodyStr = new String(body.bytes(), StandardCharsets.UTF_8);
+ Log.d("Http -> upload finish", bodyStr);
+ return bodyStr;
+ }
+ }
}
diff --git a/app/src/main/res/drawable/ic___.xml b/app/src/main/res/drawable/ic___.xml
deleted file mode 100644
index 5800208..0000000
--- a/app/src/main/res/drawable/ic___.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_upload.xml b/app/src/main/res/drawable/ic_upload.xml
new file mode 100644
index 0000000..85fedb8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_upload.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/layout_about_content.xml b/app/src/main/res/layout/layout_about_content.xml
index 14be276..8dbab40 100644
--- a/app/src/main/res/layout/layout_about_content.xml
+++ b/app/src/main/res/layout/layout_about_content.xml
@@ -279,6 +279,42 @@
+
+
+
+
+
+
+
+
+
+
+
分享软件
更新日志
GitHub
+ 分享崩溃日志
邮箱:fy@fycz.xyz
https://github.com/fengyuecanzhu/FYReader
检查更新