add plugin info on about

pull/28/head
fengyuecanzhu 2 years ago
parent de7d1ccb0d
commit 2199cc6258
No known key found for this signature in database
GPG Key ID: 04B78AD06A9D6E6C
  1. 1
      .idea/misc.xml
  2. 30
      app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java
  3. 27
      app/src/main/java/xyz/fycz/myreader/util/utils/PluginUtils.kt
  4. 36
      app/src/main/res/layout/layout_about_content.xml
  5. 1
      app/src/main/res/values/strings.xml
  6. 2
      dynamic/build.gradle
  7. 12
      dynamic/src/main/java/xyz/fycz/dynamic/AppLoadImpl.kt
  8. 11
      dynamic/src/main/java/xyz/fycz/dynamic/fix/App246Fix.kt
  9. 144
      dynamic/src/main/java/xyz/fycz/dynamic/fix/App246Fix3.kt

@ -3,6 +3,7 @@
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_about.xml" value="0.2296195652173913" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_ad_setting.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_donate.xml" value="0.264" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_more_setting.xml" value="0.2" />

@ -23,6 +23,7 @@ import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
@ -42,6 +43,7 @@ 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.entity.PluginConfig;
import xyz.fycz.myreader.model.user.UserService;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.ui.dialog.LoadingDialog;
@ -53,6 +55,7 @@ import xyz.fycz.myreader.util.ZipUtils;
import xyz.fycz.myreader.util.utils.AdUtils;
import xyz.fycz.myreader.util.utils.FileUtils;
import xyz.fycz.myreader.util.utils.OkHttpUtils;
import xyz.fycz.myreader.util.utils.PluginUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.webapi.LanZouApi;
@ -62,6 +65,8 @@ import xyz.fycz.myreader.webapi.LanZouApi;
*/
public class AboutActivity extends BaseActivity<ActivityAboutBinding> {
private PluginConfig pluginConfig;
@Override
protected void bindView() {
binding = ActivityAboutBinding.inflate(getLayoutInflater());
@ -75,11 +80,21 @@ public class AboutActivity extends BaseActivity<ActivityAboutBinding> {
getSupportActionBar().setTitle("关于");
}
@Override
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
pluginConfig = PluginUtils.INSTANCE.getConfig();
}
@Override
protected void initWidget() {
super.initWidget();
binding.il.tvVersionName.setText(String.format("风月读书v%s", App.getStrVersionName()));
binding.il.tvPlugin.setText(PluginUtils.INSTANCE.getLoadSuccess() ?
getString(R.string.plugin_version,
pluginConfig != null ? pluginConfig.getVersion() : "插件加载失败")
: "插件加载失败"
);
binding.il.rlLanZou.setVisibility(App.isDebug() ? View.VISIBLE : View.GONE);
binding.il.rlResetPangle.setVisibility(App.isDebug() ? View.VISIBLE : View.GONE);
}
@ -87,6 +102,21 @@ public class AboutActivity extends BaseActivity<ActivityAboutBinding> {
@Override
protected void initClick() {
super.initClick();
binding.il.rlPlugin.setOnClickListener(v -> {
String tip = "";
if (pluginConfig == null) {
tip = "插件配置读取失败";
} else {
if (PluginUtils.INSTANCE.getLoadSuccess()) {
tip = PluginUtils.INSTANCE.getPluginLoadInfo();
} else {
tip = PluginUtils.INSTANCE.getErrorMsg();
}
}
DialogCreator.createTipDialog(this, binding.il.tvPlugin.getText().toString(), tip);
});
ClipboardManager mClipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
binding.il.rlUpdate.setOnClickListener(v -> App.checkVersionByServer(this, true));
binding.il.rlUpdateLog.setOnClickListener(v -> DialogCreator.createAssetTipDialog(this, "更新日志", "updatelog.fy"));

@ -21,10 +21,8 @@ package xyz.fycz.myreader.util.utils
import android.content.Context
import android.util.Log
import dalvik.system.DexClassLoader
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import me.fycz.maple.MapleUtils
import xyz.fycz.dynamic.AppParam
import xyz.fycz.dynamic.IAppLoader
import xyz.fycz.myreader.application.App
@ -33,11 +31,9 @@ import xyz.fycz.myreader.common.URLCONST.DEFAULT_PLUGIN_CONFIG_URL
import xyz.fycz.myreader.entity.PluginConfig
import xyz.fycz.myreader.model.third3.Coroutine
import xyz.fycz.myreader.model.third3.http.getProxyClient
import xyz.fycz.myreader.model.third3.http.newCallResponse
import xyz.fycz.myreader.model.third3.http.newCallResponseBody
import xyz.fycz.myreader.model.third3.http.text
import xyz.fycz.myreader.util.SharedPreUtils
import xyz.fycz.myreader.util.ToastUtils
import java.io.File
import java.util.*
@ -49,12 +45,15 @@ import java.util.*
object PluginUtils {
val TAG = PluginUtils.javaClass.simpleName
private var appLoader: IAppLoader? = null
var config: PluginConfig? = null
var hasLoad = false
var loadSuccess = false
var errorMsg = ""
fun init() {
val pluginConfigUrl =
SharedPreUtils.getInstance().getString("pluginConfigUrl", DEFAULT_PLUGIN_CONFIG_URL)
var config: PluginConfig? = null
Coroutine.async {
val oldConfig = GSON.fromJsonObject<PluginConfig>(
SharedPreUtils.getInstance().getString("pluginConfig")
@ -108,7 +107,7 @@ object PluginUtils {
)
try {
val libClazz = dexClassLoader.loadClass("xyz.fycz.dynamic.AppLoadImpl")
val appLoader = libClazz.newInstance() as IAppLoader?
appLoader = libClazz.newInstance() as IAppLoader?
appLoader?.run {
val appParam = AppParam()
appParam.classLoader = context.classLoader
@ -116,13 +115,27 @@ object PluginUtils {
appParam.appInfo = context.applicationInfo
onLoad(appParam)
hasLoad = true
loadSuccess = true
}
} catch (e: Exception) {
e.printStackTrace()
errorMsg = e.stackTraceToString()
}
} else {
errorMsg = pluginPath + "文件不存在"
Log.d(TAG, pluginPath + "文件不存在")
}
}
}
fun getPluginLoadInfo(): String {
return try {
(MapleUtils.getStaticObjectField(
appLoader?.javaClass,
"pluginLoadInfo"
) as StringBuilder).toString()
} catch (e: Exception) {
""
}
}
}

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
<?xml version="1.0" encoding="utf-8"?><!--
~ This file is part of FYReader.
~ FYReader is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
@ -55,6 +54,37 @@
</LinearLayout>
<RelativeLayout
android:id="@+id/rl_plugin"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:gravity="center"
android:paddingStart="20dp"
android:paddingEnd="10dp">
<TextView
android:id="@+id/tv_plugin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="@string/plugin_version"
android:textColor="@color/textPrimary"
android:textSize="@dimen/text_normal_size" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
app:srcCompat="@drawable/ic_right_arrow"
app:tint="@color/textSecondary" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="10dp" />
<RelativeLayout
android:id="@+id/rl_update"
@ -355,6 +385,7 @@
<View
android:layout_width="match_parent"
android:layout_height="10dp" />
<RelativeLayout
android:id="@+id/rl_lan_zou"
android:layout_width="match_parent"
@ -380,6 +411,7 @@
app:srcCompat="@drawable/ic_right_arrow"
app:tint="@color/textSecondary" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rl_reset_pangle"
android:layout_width="match_parent"

@ -123,6 +123,7 @@
<string name="git_hub">GitHub</string>
<string name="share_log">分享崩溃日志</string>
<string name="this_github_url">https://github.com/fengyuecanzhu/FYReader</string>
<string name="plugin_version">插件版本:%s</string>
<string name="update">检查更新</string>
<string name="thanks">致谢名单</string>
<string name="join_qq_channel">加入QQ频道</string>

@ -54,6 +54,8 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
compileOnly("me.fycz.maple:maple:1.9")
compileOnly 'org.greenrobot:greendao:3.3.0'
compileOnly 'androidx.appcompat:appcompat:1.3.1'
compileOnly 'com.google.code.gson:gson:2.9.0'
compileOnly project(":app")
compileOnly project(":DialogX")
}

@ -39,8 +39,10 @@ class AppLoadImpl : IAppLoader {
private const val spuName = "FYReader_plugin"
val spu: SharedPreferences =
App.getmContext().getSharedPreferences(spuName, Context.MODE_PRIVATE)
val allFixInfoSb = StringBuilder()
}
private val fixList = listOf(
App243Fix::class.java,
App244Fix::class.java,
@ -48,6 +50,7 @@ class AppLoadImpl : IAppLoader {
App246Fix::class.java,
App246Fix2::class.java,
AppSubSourceFix::class.java,
App246Fix3::class.java,
)
override fun onLoad(appParam: AppParam) {
@ -67,7 +70,7 @@ class AppLoadImpl : IAppLoader {
}
if (sb.isNotEmpty()) {
if (sb.endsWith("\n")) sb.substring(0, sb.length - 1)
val key = "fix2022-06-23"
val key = "fix2022-06-28"
val hasRead = spu.getBoolean(key, false)
if (!hasRead) {
announce("插件更新", "更新内容:\n$sb")
@ -86,6 +89,13 @@ class AppLoadImpl : IAppLoader {
) {
val fix = fixClz.newInstance()
val fixResult = fix.onFix(annotation.date)
//所有修复结果信息
if (allFixInfoSb.isNotEmpty()) allFixInfoSb.append("\n")
allFixInfoSb.append("${annotation.date}\n")
fixResult.forEachIndexed { i, b ->
allFixInfoSb.append("${i + 1}${annotation.fixLog[i]}${if (b) "成功" else "失败"}\n")
}
//需要提示的修复结果信息
if (!spu.getBoolean(annotation.date, false)) {
if (sb.isNotEmpty()) sb.append("\n")
sb.append("${annotation.date}\n")

@ -22,6 +22,7 @@ import android.view.ViewGroup
import android.widget.RelativeLayout
import android.widget.ScrollView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.get
import androidx.viewbinding.ViewBinding
import me.fycz.maple.MapleBridge
@ -38,7 +39,7 @@ import xyz.fycz.myreader.util.utils.ScreenUtils
* @author fengyue
* @date 2022/6/3 15:34
*/
@AppFix([], ["[设置-缓存设置]新增清除广告文件"], "2022-06-03")
@AppFix([243, 244, 245, 246], ["[设置-缓存设置]新增清除广告文件"], "2022-06-03")
class App246Fix : AppFixHandle {
override fun onFix(key: String): BooleanArray {
@ -62,7 +63,10 @@ class App246Fix : AppFixHandle {
val binding =
MapleUtils.getObjectField(param.thisObject, "binding") as ViewBinding
val rootLayout =
binding.root.findViewById<ScrollView>(R.id.sv_content)[0] as ViewGroup
(MapleUtils.getObjectField(
binding,
"svContent"
) as ScrollView)[0] as ViewGroup
addDeleteAdFileView(rootLayout, rootLayout.childCount)
}
}
@ -83,7 +87,8 @@ class App246Fix : AppFixHandle {
ScreenUtils.dpToPx(20),
0
)
rlDeleteAdFile.background = resources.getDrawable(R.drawable.selector_common_bg)
rlDeleteAdFile.background =
ContextCompat.getDrawable(context, R.drawable.selector_common_bg)
rlDeleteAdFile.id = R.id.rl_delete_ad_file
val textview = TextView(context)
val textViewParams = RelativeLayout.LayoutParams(

@ -0,0 +1,144 @@
/*
* This file is part of FYReader.
* FYReader is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FYReader is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FYReader. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 - 2022 fengyuecanzhu
*/
package xyz.fycz.dynamic.fix
import android.annotation.SuppressLint
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.core.view.get
import androidx.core.widget.NestedScrollView
import androidx.viewbinding.ViewBinding
import me.fycz.maple.MapleBridge
import me.fycz.maple.MapleUtils
import me.fycz.maple.MethodHook
import xyz.fycz.dynamic.AppLoadImpl
import xyz.fycz.myreader.R
import xyz.fycz.myreader.base.adapter2.onClick
import xyz.fycz.myreader.entity.PluginConfig
import xyz.fycz.myreader.ui.activity.AboutActivity
import xyz.fycz.myreader.ui.dialog.DialogCreator
import xyz.fycz.myreader.util.SharedPreUtils
import xyz.fycz.myreader.util.utils.GSON
import xyz.fycz.myreader.util.utils.ScreenUtils
import xyz.fycz.myreader.util.utils.fromJsonObject
/**
* @author fengyue
* @date 2022/6/28 19:22
*/
@AppFix([243, 244, 245, 246], ["关于界面新增插件加载结果"], "2022-06-28")
class App246Fix3 : AppFixHandle {
override fun onFix(key: String): BooleanArray {
val result = try {
fxPluginView()
true
} catch (e: Exception) {
MapleUtils.log(e)
false
}
fixResult(key, "pluginView", result)
return booleanArrayOf(result)
}
private fun fxPluginView() {
MapleUtils.findAndHookMethod(
AboutActivity::class.java,
"initWidget",
object : MethodHook() {
override fun afterHookedMethod(param: MapleBridge.MethodHookParam) {
val binding =
MapleUtils.getObjectField(param.thisObject, "binding") as ViewBinding
val ilBinding = MapleUtils.getObjectField(binding, "il") as ViewBinding
val rootLayout = (ilBinding.root as NestedScrollView)[0] as ViewGroup
addPluginView(rootLayout, 1)
}
}
)
}
@SuppressLint("SetTextI18n")
fun addPluginView(rootLayout: ViewGroup, index: Int) {
val pluginConfig = GSON.fromJsonObject<PluginConfig>(
SharedPreUtils.getInstance().getString("pluginConfig")
) ?: PluginConfig("dynamic.dex", 100)
val context = rootLayout.context
val rlPlugin = RelativeLayout(context)
val pluginLayoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ScreenUtils.dpToPx(50)
)
rlPlugin.background = ContextCompat.getDrawable(context, R.drawable.selector_common_bg)
rlPlugin.gravity = Gravity.CENTER
rlPlugin.id = R.id.rl_update
rlPlugin.setPadding(
ScreenUtils.dpToPx(20),
0,
ScreenUtils.dpToPx(10),
0
)
val textview = TextView(context)
val textviewLayoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
addRule(RelativeLayout.CENTER_VERTICAL)
}
textview.text = "插件版本:${pluginConfig.version}"
textview.setTextColor(context.resources.getColor(R.color.textPrimary))
textview.textSize =
ScreenUtils.pxToSp(
context.resources.getDimension(R.dimen.text_normal_size).toInt()
).toFloat()
rlPlugin.addView(textview, textviewLayoutParams)
val imageView = AppCompatImageView(context)
val imageViewLayoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
).apply {
addRule(RelativeLayout.ALIGN_PARENT_END)
addRule(RelativeLayout.CENTER_VERTICAL)
}
imageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_right_arrow))
imageView.drawable.setTint(context.resources.getColor(R.color.textPrimary))
rlPlugin.addView(imageView, imageViewLayoutParams)
rlPlugin.onClick {
DialogCreator.createTipDialog(
context,
"插件版本:${pluginConfig.version}",
"当前版本更新日志:\n${pluginConfig.changelog}\n\n插件加载结果:\n" +
AppLoadImpl.allFixInfoSb.toString()
)
}
rootLayout.addView(rlPlugin, index, pluginLayoutParams)
val view = View(context)
val layoutParams = ViewGroup.MarginLayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ScreenUtils.dpToPx(10)
)
rootLayout.addView(view, index + 1, layoutParams)
}
}
Loading…
Cancel
Save