Merge branch 'ota'

This commit is contained in:
Vologhat
2022-06-16 00:09:40 +03:00
15 changed files with 461 additions and 61 deletions
+1 -1
View File
@@ -15007,7 +15007,7 @@ public final class R {
public static final int dockbar_save = 0x7f11123b;
public static final int dockbar_selected_items = 0x7f11123c;
public static final int dockbar_unselected_items = 0x7f11123d;
public static final int download_latest_vtl = 0x7f11123e;
public static final int checkforupdates = 0x7f11123e;
public static final int other_fix_dynamic_colors = 0x7f11123f;
public static final int other_reset_settings = 0x7f111240;
public static final int other_reset_settings_summary = 0x7f111241;
@@ -0,0 +1,70 @@
package ru.vtosters.lite.downloaders;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Environment;
import com.vk.core.f.FileUtils;
import java.io.File;
import ru.vtosters.lite.ui.activities.APKInstallActivity;
import ru.vtosters.lite.utils.Globals;
public class OTADownloader {
private static final BroadcastReceiver callback = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
var extras = intent.getExtras();
if (extras == null
|| !intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) return;
var query = new DownloadManager.Query();
var id = extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
query.setFilterById(id);
var manager = (DownloadManager) Globals.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
var cursor = manager.query(query);
if (cursor.moveToFirst()) {
var status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
var downloadDir = new File(Environment.getExternalStorageDirectory(), "Download");
if (!downloadDir.exists()) return;
var list = downloadDir.listFiles();
if (list == null || list.length == 0) return;
var maxIndex = -1;
for (File file : list) {
var name = file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf("/") + 1);
if (file.isFile()
&& name.matches("VTLite-\\d+\\.apk"))
maxIndex = Math.max(maxIndex, Integer.parseInt(name.replaceFirst(".+-(\\d+).+", "$1")));
}
File apk = maxIndex == -1 ? new File(downloadDir, "VTLite.apk") : new File(downloadDir, "VTLite-" + maxIndex + ".apk");
APKInstallActivity.installOta(context, FileUtils.h(apk));
} else if (status == DownloadManager.STATUS_FAILED) {
// do something
}
}
}
};
public static void downloadBuild(String url) {
var context = Globals.getContext();
url = "https://github.com/vtosters/lite/releases/download/v0.2.9-beta2/VTLite.apk";
var uri = Uri.parse(url);
context.registerReceiver(callback, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
var request = new DownloadManager.Request(uri);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setTitle("VTLite.apk");
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "VTLite.apk");
var manager = (DownloadManager) Globals.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
}
@@ -0,0 +1,80 @@
package ru.vtosters.lite.ui.activities;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
public class APKInstallActivity extends AppCompatActivity {
public static final int REQUEST_INSTALL_PERMISSION = 1;
public static final String EXTRA_APK_URI = "apk_uri";
private Uri mApkUri;
public static void installOta(Context context, Uri apkUri) {
Intent intent = new Intent(context, APKInstallActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(EXTRA_APK_URI, apkUri);
context.startActivity(intent);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent == null) {
Toast.makeText(this, "No intent", Toast.LENGTH_SHORT).show();
finish();
return;
}
mApkUri = intent.getParcelableExtra(EXTRA_APK_URI);
if (mApkUri == null) {
Toast.makeText(this, "No apk uri", Toast.LENGTH_SHORT).show();
finish();
return;
}
installApk();
}
private void installApk() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!getPackageManager().canRequestPackageInstalls()) {
Intent permIntent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + getPackageName()));
startActivityForResult(permIntent, REQUEST_INSTALL_PERMISSION);
return;
}
}
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(mApkUri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (Exception e) {
Toast.makeText(this, "Ошибка установки обновления " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
finish();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_INSTALL_PERMISSION)
installApk();
}
}
@@ -0,0 +1,46 @@
package ru.vtosters.lite.ui.dialogs;
import android.app.Activity;
import android.widget.Toast;
import ru.vtosters.lite.downloaders.OTADownloader;
import ru.vtosters.lite.ui.vkui.ModalBottomSheetWrapper;
import ru.vtosters.lite.utils.OTAHelper;
public class OTADialog implements OTAHelper.OTAListener {
private Activity mActivity;
private OTAHelper mHelper;
public static OTADialog checkUpdates(Activity activity) {
return new OTADialog(activity);
}
public OTADialog(Activity activity) {
mActivity = activity;
mHelper = new OTAHelper(this);
mHelper.loadData();
}
@Override
public void onUpdateApplied() {
mActivity.runOnUiThread(() -> {
Toast.makeText(mActivity, "Обновления найдены", Toast.LENGTH_SHORT).show();
new ModalBottomSheetWrapper(mActivity)
.setUpdateInfoView(mHelper.getNewVersionName(), mHelper.getUpdateDescription())
.setPositiveButton("Обновить", () -> {
OTADownloader.downloadBuild(mHelper.getDownloadUrl());
})
.show();
});
}
@Override
public void onUpdateCanceled() {
mActivity.runOnUiThread(() -> {
Toast.makeText(mActivity, "Обновлений не найдено", Toast.LENGTH_SHORT).show();
});
}
}
@@ -56,6 +56,7 @@ import com.vtosters.lite.fragments.k.BlacklistFragment;
import com.vtosters.lite.fragments.money.music.control.subscription.MusicSubscriptionControlFragment;
import ru.vtosters.lite.ui.PreferencesUtil;
import ru.vtosters.lite.ui.dialogs.OTADialog;
import ru.vtosters.lite.ui.fragments.dockbar.DockBarFragment;
import ru.vtosters.lite.ui.fragments.dockbar.DockBarManager;
import ru.vtosters.lite.ui.fragments.multiaccount.MultiAccountFragment;
@@ -336,10 +337,20 @@ public class VTSettings extends MaterialPreferenceToolbarFragment {
return false;
});
PreferencesUtil.addPreference(this, "", getString("download_latest_vtl"), "", "ic_download_24", preference -> {
getContext().startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse("https://github.com/vtosters/lite/releases/latest")));
PreferencesUtil.addPreferenceCategory(this, getString("updates"));
PreferencesUtil.addPreference(this, "", getString("checkforupdates"), "", "ic_download_24", preference -> {
OTADialog.checkUpdates(p());
return false;
});
PreferencesUtil.addMaterialSwitchPreference(this, "checkupdates", getString("checkupdates"), "", "ic_recent_24", true, (preference, o) -> {
boolean value = (boolean) o;
edit().putBoolean("checkupdates", value).commit();
return true;
});
}
public static String getValAsString(String stringid, Boolean value) {
@@ -1,50 +0,0 @@
package ru.vtosters.lite.ui.vkui;
import android.app.Activity;
import android.view.View;
import com.vk.core.dialogs.bottomsheet.ModalBottomSheet;
public class ModalBottomSheetProxy {
public final ModalBottomSheet.a builder;
public ModalBottomSheetProxy(Activity activity) {
builder = new ModalBottomSheet.a(activity);
}
public void setTitle(String title) {
builder.b(title);
}
public void setClickableMessage(String text) {
builder.a(text, kostil -> {
});
}
public void setClickableMessage(String text, Runnable runnable) {
builder.a(text, listener -> runnable.run());
}
public void setPositiveButton(String text, Runnable runnable) {
builder.b(text, kostil -> runnable.run());
}
public void setSubtitle(String text) {
builder.b((CharSequence) text);
}
public void setView(View view) {
builder.a(view);
}
public ModalBottomSheet show() {
return builder.c(null);
}
public ModalBottomSheet show(boolean isCancellable) {
var sheet = builder.c(null);
sheet.b(isCancellable);
return sheet;
}
}
@@ -0,0 +1,97 @@
package ru.vtosters.lite.ui.vkui;
import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.vk.core.dialogs.bottomsheet.ModalBottomSheet;
import ru.vtosters.lite.utils.Globals;
import ru.vtosters.lite.utils.Themes;
public class ModalBottomSheetWrapper {
public final ModalBottomSheet.a builder;
public ModalBottomSheetWrapper(Activity activity) {
builder = new ModalBottomSheet.a(activity);
}
public ModalBottomSheetWrapper setTitle(String title) {
builder.b(title);
return this;
}
public ModalBottomSheetWrapper setUpdateInfoView(String version, String changelog) {
var context = Globals.getContext();
var container = new LinearLayout(context);
var title = new TextView(context);
var changelogView = new TextView(context);
container.setOrientation(LinearLayout.VERTICAL);
title.setText("Новая версия " + version);
title.setTypeface(title.getTypeface(), Typeface.BOLD);
title.setSingleLine(true);
title.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
title.setTextColor(Themes.getTextAttr());
title.setTextSize(24.0f);
container.addView(title, new LinearLayout.LayoutParams(-1, -2));
changelogView.setPadding(0, Globals.convertDpToPixel(8), 0, 0);
changelogView.setText("Изменения: \n" + changelog);
changelogView.setTextColor(Themes.getTextAttr());
container.addView(changelogView, new LinearLayout.LayoutParams(-1, -2));
builder.a(container);
return this;
}
// try to call a true function and you will understand my pain
public ModalBottomSheetWrapper setMessage(
String text
) {
builder.a(text, listener -> {});
return this;
}
public ModalBottomSheetWrapper setClickableMessage(
String text,
Runnable callback
) {
builder.a(text, listener -> callback.run());
return this;
}
public ModalBottomSheetWrapper setPositiveButton(
String text,
Runnable callback
) {
builder.b(text, kostil -> callback.run());
return this;
}
public ModalBottomSheetWrapper setSubtitle(String text) {
builder.b((CharSequence) text);
return this;
}
public ModalBottomSheetWrapper setView(View view) {
builder.a(view);
return this;
}
public ModalBottomSheet show() {
return builder.c(null);
}
public ModalBottomSheet show(boolean isCancellable) {
var sheet = builder.c(null);
sheet.b(isCancellable);
return sheet;
}
}
@@ -1,6 +1,7 @@
package ru.vtosters.lite.utils;
import static androidx.core.content.ContextCompat.getDrawable;
import static ru.vtosters.lite.utils.Preferences.checkupdates;
import static ru.vtosters.lite.utils.Preferences.getLocale;
import static ru.vtosters.lite.utils.Preferences.preferences;
import static ru.vtosters.lite.utils.Themes.isDarkTheme;
@@ -49,6 +50,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import ru.vtosters.lite.ui.dialogs.DisableBattery;
import ru.vtosters.lite.ui.dialogs.InstallGMS;
import ru.vtosters.lite.ui.dialogs.Start;
import ru.vtosters.lite.ui.dialogs.OTADialog;
public class Globals {
private static final List<Activity> activities = new ArrayList<>();
@@ -57,6 +63,14 @@ public class Globals {
return preferences;
}
public static void MainActivityInit(Activity activity) {
if(checkupdates())
OTADialog.checkUpdates(activity);
Start.alert(activity);
InstallGMS.alert(activity);
DisableBattery.alert(activity);
}
public static void componentSwitcher(String component, Boolean enabled) {
var packageManager = getContext().getPackageManager();
packageManager.setComponentEnabledSetting(new ComponentName(getPackageName(), getPackageName() + "." + component), enabled? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
@@ -0,0 +1,126 @@
package ru.vtosters.lite.utils;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OTAHelper {
private static final String LATEST_RELEASE_URL = "https://api.github.com/repositories/473685743/releases/latest";
private static final String LATEST_RELEASE_COMMIT_URL = "https://api.github.com/repositories/473685743/git/ref/tags/%s";
private OTAListener mListener;
private final OkHttpClient mClient = new OkHttpClient();
private JSONObject mReleaseJson;
private JSONObject mCommitJson;
public OTAHelper(OTAListener listener) {
this.mListener = listener;
}
public void loadData() {
Request release = new Request.Builder()
.url(LATEST_RELEASE_URL)
.build();
mClient.newCall(release).a(new Callback() {
@Override
public void a(Call call, IOException e) {
Log.d("OTAHelper", "Error while getting latest release info: " + e);
mListener.onUpdateCanceled();
}
@Override
public void a(Call call, Response response) throws IOException {
try {
setData(response);
} catch (JSONException | NullPointerException e) {
e.printStackTrace();
}
}
});
}
void setData(Response response) throws IOException, JSONException {
mReleaseJson = new JSONObject(response.body().string());
String tag = mReleaseJson.getString("tag_name");
Request commit = new Request.Builder()
.url(String.format(LATEST_RELEASE_COMMIT_URL, tag))
.build();
mClient.newCall(commit).a(new Callback() {
@Override
public void a(Call call, IOException e) {
Log.d("OTAHelper", "Error while getting latest commit info: " + e);
mListener.onUpdateCanceled();
}
@Override
public void a(Call call, Response response) throws IOException {
try {
mCommitJson = new JSONObject(response.body().string());
if (isNewVersion())
mListener.onUpdateApplied();
else mListener.onUpdateCanceled();
} catch (NullPointerException | JSONException e) {
e.printStackTrace();
mListener.onUpdateCanceled();
}
}
});
}
public boolean isNewVersion() {
try {
String commitSHA = mCommitJson.getJSONObject("object").getString("sha");
return !commitSHA.startsWith(About.getBuildNumber());
} catch (Exception e) {
return false;
}
}
public String getNewVersionName() {
try {
return mReleaseJson.getString("name");
} catch (JSONException e) {
return null;
}
}
public String getUpdateDescription() {
try {
return mReleaseJson.getString("body");
} catch (JSONException e) {
return null;
}
}
public String getDownloadUrl() {
try {
return mReleaseJson.getJSONArray("assets")
.getJSONObject(0)
.getString("browser_download_url");
} catch (JSONException e) {
return null;
}
}
public interface OTAListener {
void onUpdateApplied();
void onUpdateCanceled();
}
}
@@ -361,6 +361,10 @@ public class Preferences {
return getBoolValue("roundedmsgs", false);
}
public static boolean checkupdates() {
return getBoolValue("checkupdates", true);
}
public static boolean disableanimstickers() {
return getBoolValue("disableanimstickers", true);
}
+1
View File
@@ -75,6 +75,7 @@
<meta-data android:name="com.facebook.sdk.CodelessDebugLogEnabled" android:value="false"/>
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/cornflower_blue"/>
<activity android:name="ru.vtosters.lite.ui.activities.APKInstallActivity" />
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize" android:label="@string/app_name" android:launchMode="singleTask" android:name="com.vtosters.lite.MainActivity" android:theme="@style/SplashTheme">
<intent-filter>
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER"/>
+3 -1
View File
@@ -4337,7 +4337,7 @@
<string name="add_another_account">Добавить новый аккаунт</string>
<string name="download_latest_vtl">Скачать последнюю версию</string>
<string name="checkforupdates">Проверить обновления</string>
<string name="debug_warning">Внимание!</string>
<string name="debug_warning_summary">Данное меню предназначено только для тестирования работоспособности приложения. Если вы являетесь рядовым юзером, то вам не следует ничего не трогать в данных настройках (пожалуйста)</string>
@@ -4474,6 +4474,8 @@
<string name="vtlhidesumm">Скрыть подписи в настройках</string>
<string name="vtlssfssumm">Есть доступ</string>
<string name="checkupdates">Авто обновления</string>
<string name="updates">Обновления</string>
<string name="empty_text" />
</resources>
+1 -1
View File
@@ -14953,7 +14953,7 @@
<public type="string" name="dockbar_save" id="0x7f11123b" />
<public type="string" name="dockbar_selected_items" id="0x7f11123c" />
<public type="string" name="dockbar_unselected_items" id="0x7f11123d" />
<public type="string" name="download_latest_vtl" id="0x7f11123e" />
<public type="string" name="checkforupdates" id="0x7f11123e" />
<public type="string" name="other_fix_dynamic_colors" id="0x7f11123f" />
<public type="string" name="other_reset_settings" id="0x7f111240" />
<public type="string" name="other_reset_settings_summary" id="0x7f111241" />
+4 -1
View File
@@ -4463,7 +4463,7 @@ May look like a fake leaving the online"</string>
<string name="add_another_account">Add new account</string>
<string name="download_latest_vtl">Download latest version</string>
<string name="checkforupdates">Check for updates</string>
<string name="debug_warning">Warning!</string>
<string name="debug_warning_summary">These options are for testing this app only. If you are a regular user, please, don\'t use them</string>
@@ -4608,6 +4608,9 @@ May look like a fake leaving the online"</string>
<string name="vtlhidesumm">Hide settings summaries</string>
<string name="vtlssfssumm">Have access</string>
<string name="checkupdates">Auto updates</string>
<string name="updates">Updates</string>
<item type="string" name="APKTOOL_DUMMY_10be" />
<item type="string" name="APKTOOL_DUMMY_10bf" />
@@ -566,11 +566,7 @@
.line 65
:cond_0
invoke-static {p0}, Lru/vtosters/lite/ui/dialogs/Start;->alert(Landroid/app/Activity;)V
invoke-static {p0}, Lru/vtosters/lite/ui/dialogs/InstallGMS;->alert(Landroid/app/Activity;)V
invoke-static {p0}, Lru/vtosters/lite/ui/dialogs/DisableBattery;->alert(Landroid/app/Activity;)V
invoke-static {p0}, Lru/vtosters/lite/utils/Globals;->MainActivityInit(Landroid/app/Activity;)V
invoke-virtual {p0}, Lcom/vtosters/lite/MainActivity;->getWindow()Landroid/view/Window;