[app] Check update (#768)

This commit is contained in:
vvb2060 2021-06-24 04:20:11 +08:00 committed by GitHub
parent 1eebbca320
commit 612c39d325
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 88 additions and 32 deletions

View File

@ -21,6 +21,7 @@ import com.android.build.api.variant.impl.ApplicationVariantImpl
import com.android.build.api.component.analytics.AnalyticsEnabledApplicationVariant
import com.android.build.gradle.internal.dsl.BuildType
import java.nio.file.Paths
import java.time.Instant
plugins {
id("org.gradle.idea")
@ -88,6 +89,7 @@ android {
"pt",
"es",
)
buildConfigField("long", "BUILD_TIME", Instant.now().epochSecond.toString())
}
compileOptions {

View File

@ -30,6 +30,8 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;
import com.google.gson.JsonParser;
import org.lsposed.hiddenapibypass.HiddenApiBypass;
import org.lsposed.manager.repo.RepoLoader;
import org.lsposed.manager.ui.activity.CrashReportActivity;
@ -37,13 +39,20 @@ import org.lsposed.manager.util.DoHDNS;
import org.lsposed.manager.util.theme.ThemeUtil;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Locale;
import okhttp3.Cache;
import okhttp3.MediaType;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import rikka.material.app.DayNightDelegate;
@ -63,9 +72,6 @@ public class App extends Application {
private static Cache okHttpCache;
private SharedPreferences pref;
public static final MediaType JSON
= MediaType.get("application/json; charset=utf-8");
public static App getInstance() {
return instance;
@ -117,6 +123,7 @@ public class App extends Application {
DayNightDelegate.setApplicationContext(this);
DayNightDelegate.setDefaultNightMode(ThemeUtil.getDarkTheme());
RepoLoader.getInstance().loadRemoteData();
loadRemoteVersion();
}
@NonNull
@ -144,4 +151,51 @@ public class App extends Application {
}
return okHttpCache;
}
private void loadRemoteVersion() {
var request = new Request.Builder()
.url("https://api.github.com/repos/LSPosed/LSPosed/releases/latest")
.addHeader("Accept", "application/vnd.github.v3+json")
.build();
var callback = new Callback() {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
if (!response.isSuccessful()) return;
var body = response.body();
if (body == null) return;
try {
var info = JsonParser.parseReader(body.charStream()).getAsJsonObject();
var published = info.get("published_at").getAsString();
var time = LocalDateTime.parse(published).toInstant(ZoneOffset.UTC).getEpochSecond();
var now = Instant.now().getEpochSecond();
pref.edit().putLong("latest_release", time).putLong("latest_check", now).apply();
} catch (Throwable t) {
Log.e(App.TAG, t.getMessage(), t);
}
}
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
Log.e(App.TAG, e.getMessage(), e);
}
};
getOkHttpClient().newCall(request).enqueue(callback);
}
public static boolean needUpdate() {
var now = Instant.now();
var buildTime = Instant.ofEpochSecond(BuildConfig.BUILD_TIME);
var check = getPreferences().getLong("latest_check", 0);
if (check > 0) {
var checkTime = Instant.ofEpochSecond(check);
if (checkTime.atOffset(ZoneOffset.UTC).plusDays(30).toInstant().isBefore(now))
return true;
var release = getPreferences().getLong("latest_release", 0);
if (release > 0) {
var releaseTime = Instant.ofEpochSecond(release);
return releaseTime.atOffset(ZoneOffset.UTC).minusDays(1).toInstant().isAfter(buildTime);
}
}
return buildTime.atOffset(ZoneOffset.UTC).plusDays(30).toInstant().isBefore(now);
}
}

View File

@ -178,9 +178,11 @@ public class RepoLoader {
}
public interface Listener {
void repoLoaded();
default void repoLoaded() {
}
void moduleReleasesLoaded(OnlineModule module);
default void moduleReleasesLoaded(OnlineModule module) {
}
void onThrowable(Throwable t);
}

View File

@ -23,7 +23,6 @@ package org.lsposed.manager.ui.activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.Bundle;
@ -51,7 +50,7 @@ public class CrashReportActivity extends AppCompatActivity {
binding = ActivityCrashReportBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.copyLogs.setOnClickListener(v -> {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
var clipboard = getSystemService(ClipboardManager.class);
//Are there any devices without clipboard...?
if (clipboard != null) {
ClipData clip = ClipData.newPlainText("LSPManagerCrashInfo", getAllErrorDetailsFromIntent(getIntent()));
@ -66,26 +65,29 @@ public class CrashReportActivity extends AppCompatActivity {
Date currentDate = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
String versionName = getVersionName();
String versionName = String.format("%s (%s)", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE);
String errorDetails = "";
errorDetails += "Build version: " + versionName + " \n";
errorDetails += "Current date: " + dateFormat.format(currentDate) + " \n";
errorDetails += "Device: " + getDeviceModelName() + " \n \n";
errorDetails += "Device: " + getDeviceModelName() + " \n";
errorDetails += "Fingerprint: " + getFingerprint() + " \n \n";
errorDetails += "SDK: " + Build.VERSION.SDK_INT + " \n \n";
errorDetails += "Stack trace: \n";
errorDetails += getStackTraceFromIntent(intent);
return errorDetails;
}
private String getVersionName() {
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
return String.format("%s (%s)", packageInfo.versionName, packageInfo.versionCode);
} catch (Exception e) {
return "Unknown";
}
private String getFingerprint() {
return Build.BRAND + '/' +
Build.PRODUCT + '/' +
Build.DEVICE + ':' +
Build.VERSION.RELEASE + '/' +
Build.ID + '/' +
Build.VERSION.INCREMENTAL + ':' +
Build.TYPE + '/' +
Build.TAGS;
}
private String getDeviceModelName() {

View File

@ -32,6 +32,7 @@ import androidx.core.text.HtmlCompat;
import com.bumptech.glide.Glide;
import com.google.android.material.snackbar.Snackbar;
import org.lsposed.manager.App;
import org.lsposed.manager.BuildConfig;
import org.lsposed.manager.ConfigManager;
import org.lsposed.manager.R;
@ -118,6 +119,11 @@ public class HomeFragment extends BaseFragment {
cardBackgroundColor = ResourcesKt.resolveColor(activity.getTheme(), R.attr.colorWarning);
binding.statusIcon.setImageResource(R.drawable.ic_warning);
binding.statusSummary.setText(R.string.system_prop_incorrect_summary);
} else if (App.needUpdate()) {
binding.statusTitle.setText(R.string.need_update);
cardBackgroundColor = ResourcesKt.resolveColor(activity.getTheme(), R.attr.colorWarning);
binding.statusIcon.setImageResource(R.drawable.ic_warning);
binding.statusSummary.setText(R.string.please_update_summary);
} else {
binding.statusTitle.setText(R.string.activated);
cardBackgroundColor = ResourcesKt.resolveColor(activity.getTheme(), R.attr.colorNormal);

View File

@ -147,11 +147,6 @@ public class RepoFragment extends BaseFragment implements RepoLoader.Listener {
});
}
@Override
public void moduleReleasesLoaded(OnlineModule module) {
}
@Override
public void onThrowable(Throwable t) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
@ -202,9 +197,7 @@ public class RepoFragment extends BaseFragment implements RepoLoader.Listener {
sb.append(summary);
}
holder.appDescription.setText(sb);
holder.itemView.setOnClickListener(v -> {
getNavController().navigate(RepoFragmentDirections.actionRepoFragmentToRepoItemFragment(module.getName(), module.getDescription()));
});
holder.itemView.setOnClickListener(v -> getNavController().navigate(RepoFragmentDirections.actionRepoFragmentToRepoItemFragment(module.getName(), module.getDescription())));
}
@Override

View File

@ -31,9 +31,7 @@ import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.RenderProcessGoneDetail;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@ -195,11 +193,6 @@ public class RepoItemFragment extends BaseFragment implements RepoLoader.Listene
return super.onOptionsItemSelected(item);
}
@Override
public void repoLoaded() {
}
@Override
public void moduleReleasesLoaded(OnlineModule module) {
this.module = module;

View File

@ -39,12 +39,14 @@
<string name="activated">已激活</string>
<string name="not_installed">未安装</string>
<string name="partial_activated">部分激活</string>
<string name="need_update">需要更新</string>
<string name="selinux_policy_not_loaded_summary">SEPolicy 未被正确加载</string>
<string name="selinux_policy_not_loaded"><![CDATA[<b>警告:</b>SEPolicy 未被正确加载,作用于系统框架的模块将不起作用。<br>请将此报告给 <a href="https://github.com/topjohnwu/Magisk/issues"><b>Magisk</b></a> 开发者。]]></string>
<string name="system_inject_fail_summary">系统框架注入失败</string>
<string name="system_inject_fail"><![CDATA[<b>警告:</b>系统注入失败。<br/>这是极罕见的情况,可能是由 <b>Magisk</b> 或低质 Magisk 模块导致。<br/>请尝试禁用除 Riru 和 LSPosed 外的 Magisk 模块,或向开发者提供完整日志。]]></string>
<string name="system_prop_incorrect_summary">系统属性异常</string>
<string name="system_prop_incorrect"><![CDATA[<b>警告:</b>系统属性异常。<br/>一些必须的系统属性被删除或被修改。<br/>模块可能会随机失效。]]></string>
<string name="please_update_summary">请安装新版 LSPosed</string>
<string name="info_api_version">API 版本</string>
<string name="info_framework_version">框架版本</string>
<string name="info_manager_version">管理器版本</string>

View File

@ -39,12 +39,14 @@
<string name="activated">Activated</string>
<string name="not_installed">Not installed</string>
<string name="partial_activated">Partially activated</string>
<string name="need_update">Need to update</string>
<string name="selinux_policy_not_loaded_summary">SEPolicy is not loaded properly</string>
<string name="selinux_policy_not_loaded"><![CDATA[<b>WARNING:</b> SEPolicy is not loaded properly, modules that hook System Framework will not work.<br/>Please report this to <a href="https://github.com/topjohnwu/Magisk/issues"><b>Magisk</b></a> developer.]]></string>
<string name="system_inject_fail_summary">System Framework injection failed</string>
<string name="system_inject_fail"><![CDATA[<b>WARNING:</b> System Framework inject failed.<br/>This is rare and may be caused by <b>Magisk</b> or some low-quality Magisk modules.<br/>Please try to disable Magisk modules other than Riru and LSPosed or submit full log to developers.]]></string>
<string name="system_prop_incorrect_summary">System prop incorrect</string>
<string name="system_prop_incorrect"><![CDATA[<b>WARNING:</b> System prop incorrect.<br/>Some necessary system properties deleted or modified.<br/>Modules may invalidate occasionally.]]></string>
<string name="please_update_summary">Please install the latest version of LSPosed</string>
<string name="info_api_version">API version</string>
<string name="info_framework_version">Framework version</string>
<string name="info_manager_version">Manager version</string>