This repository was archived by the owner on Feb 12, 2026. It is now read-only.
forked from JingMatrix/LSPosed
-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathUpdateUtil.java
More file actions
149 lines (136 loc) · 5.82 KB
/
UpdateUtil.java
File metadata and controls
149 lines (136 loc) · 5.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
* This file is part of LSPosed.
*
* LSPosed 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.
*
* LSPosed 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 LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2022 LSPosed Contributors
*/
package org.lsposed.manager.util;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.lsposed.manager.App;
import org.lsposed.manager.BuildConfig;
import org.lsposed.manager.ConfigManager;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Locale;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Request;
import okhttp3.Response;
import okio.Okio;
public class UpdateUtil {
public static void loadRemoteVersion() {
var request = new Request.Builder()
.url("https://api.github.com/repos/ThePedroo/ReLSPosed/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;
String api = ConfigManager.isBinderAlive() ? ConfigManager.getApi() : "riru";
try {
var info = JsonParser.parseReader(body.charStream()).getAsJsonObject();
var notes = info.get("body").getAsString();
var assetsArray = info.getAsJsonArray("assets");
for (var assets : assetsArray) {
checkAssets(assets.getAsJsonObject(), notes, api.toLowerCase(Locale.ROOT));
}
} catch (Throwable t) {
Log.e(App.TAG, t.getMessage(), t);
}
}
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
Log.e(App.TAG, "loadRemoteVersion: " + e.getMessage());
var pref = App.getPreferences();
if (pref.getBoolean("checked", false)) return;
pref.edit().putBoolean("checked", true).apply();
}
};
App.getOkHttpClient().newCall(request).enqueue(callback);
}
private static void checkAssets(JsonObject assets, String releaseNotes, String api) {
var pref = App.getPreferences();
var name = assets.get("name").getAsString();
var splitName = name.split("-");
if (!splitName[3].equals(api)) return;
pref.edit()
.putInt("latest_version", Integer.parseInt(splitName[2]))
.putLong("latest_check", Instant.now().getEpochSecond())
.putString("release_notes", releaseNotes)
.putString("zip_file", null)
.putBoolean("checked", true)
.apply();
var updatedAt = Instant.parse(assets.get("updated_at").getAsString());
var downloadUrl = assets.get("browser_download_url").getAsString();
var zipTime = pref.getLong("zip_time", 0);
if (!updatedAt.equals(Instant.ofEpochSecond(zipTime))) {
var zip = downloadNewZipSync(downloadUrl, name);
var size = assets.get("size").getAsLong();
if (zip != null && zip.length() == size) {
pref.edit()
.putLong("zip_time", updatedAt.getEpochSecond())
.putString("zip_file", zip.getAbsolutePath())
.apply();
}
}
}
public static boolean needUpdate() {
var pref = App.getPreferences();
if (!pref.getBoolean("checked", false)) return false;
var now = Instant.now();
var buildTime = Instant.ofEpochSecond(BuildConfig.BUILD_TIME);
var check = pref.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 code = pref.getInt("latest_version", 0);
return code > BuildConfig.VERSION_CODE;
}
return buildTime.atOffset(ZoneOffset.UTC).plusDays(30).toInstant().isBefore(now);
}
@Nullable
private static File downloadNewZipSync(String url, String name) {
var request = new Request.Builder().url(url).build();
var zip = new File(App.getInstance().getCacheDir(), name);
try (Response response = App.getOkHttpClient().newCall(request).execute()) {
var body = response.body();
if (!response.isSuccessful() || body == null) return null;
try (var source = body.source();
var sink = Okio.buffer(Okio.sink(zip))) {
sink.writeAll(source);
}
} catch (IOException e) {
Log.e(App.TAG, "downloadNewZipSync: " + e.getMessage());
return null;
}
return zip;
}
public static boolean canInstall() {
if (!ConfigManager.isBinderAlive()) return false;
var pref = App.getPreferences();
var zip = pref.getString("zip_file", null);
return zip != null && new File(zip).isFile();
}
}