diff --git a/app/src/main/java/ru/vtosters/lite/downloaders/OTADownloader.java b/app/src/main/java/ru/vtosters/lite/downloaders/OTADownloader.java
new file mode 100644
index 000000000..e866e57f7
--- /dev/null
+++ b/app/src/main/java/ru/vtosters/lite/downloaders/OTADownloader.java
@@ -0,0 +1,56 @@
+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 android.widget.HeaderViewListAdapter;
+
+import ru.vtosters.lite.ui.activities.APKInstallActivity;
+import ru.vtosters.lite.ui.vkui.ModalBottomSheetWrapper;
+import ru.vtosters.lite.utils.Globals;
+
+public class OTADownloader {
+
+ private static 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();
+ long 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 uri = Uri.parse(cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI)));
+ APKInstallActivity.installOta(Globals.getContext(), uri);
+ } else if (status == DownloadManager.STATUS_FAILED) {
+
+ }
+ }
+ }
+ };
+
+ public static void downloadBuild(String url) {
+ var context = Globals.getContext();
+ 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);
+ }
+}
diff --git a/app/src/main/java/ru/vtosters/lite/ui/activities/APKInstallActivity.java b/app/src/main/java/ru/vtosters/lite/ui/activities/APKInstallActivity.java
new file mode 100644
index 000000000..3dd5f7987
--- /dev/null
+++ b/app/src/main/java/ru/vtosters/lite/ui/activities/APKInstallActivity.java
@@ -0,0 +1,82 @@
+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.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+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(@Nullable 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, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_INSTALL_PERMISSION)
+ installApk();
+ }
+}
diff --git a/app/src/main/java/ru/vtosters/lite/ui/dialogs/OTADialog.java b/app/src/main/java/ru/vtosters/lite/ui/dialogs/OTADialog.java
index 12aac90b9..1d3c568c3 100644
--- a/app/src/main/java/ru/vtosters/lite/ui/dialogs/OTADialog.java
+++ b/app/src/main/java/ru/vtosters/lite/ui/dialogs/OTADialog.java
@@ -1,16 +1,19 @@
package ru.vtosters.lite.ui.dialogs;
import android.app.Activity;
+import android.text.Html;
import android.widget.Toast;
import com.vk.core.dialogs.VKProgressDialog;
+import ru.vtosters.lite.downloaders.OTADownloader;
+import ru.vtosters.lite.ui.vkui.ModalBottomSheetWrapper;
+import ru.vtosters.lite.utils.Globals;
import ru.vtosters.lite.utils.OTAHelper;
public class OTADialog implements OTAHelper.OTAListener {
private Activity mActivity;
- private VKProgressDialog mProgressDialog;
private OTAHelper mHelper;
@@ -21,11 +24,6 @@ public class OTADialog implements OTAHelper.OTAListener {
public OTADialog(Activity activity) {
mActivity = activity;
- mProgressDialog = new VKProgressDialog(activity);
- mProgressDialog.setTitle("Проверка обновлений...");
- mProgressDialog.setCancelable(false);
- mProgressDialog.show();
-
mHelper = new OTAHelper(this);
mHelper.loadData();
}
@@ -34,7 +32,12 @@ public class OTADialog implements OTAHelper.OTAListener {
public void onUpdateApplied() {
mActivity.runOnUiThread(() -> {
Toast.makeText(mActivity, "Обновления найдены", Toast.LENGTH_SHORT).show();
- mProgressDialog.dismiss();
+ new ModalBottomSheetWrapper(mActivity)
+ .setUpdateInfoView(mHelper.getNewVersionName(), mHelper.getUpdateDescription())
+ .setPositiveButton("Обновить", () -> {
+ OTADownloader.downloadBuild(mHelper.getDownloadUrl());
+ })
+ .show();
});
}
@@ -42,7 +45,6 @@ public class OTADialog implements OTAHelper.OTAListener {
public void onUpdateCanceled() {
mActivity.runOnUiThread(() -> {
Toast.makeText(mActivity, "Обновлений не найдено", Toast.LENGTH_SHORT).show();
- mProgressDialog.dismiss();
});
}
}
diff --git a/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetProxy.java b/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetProxy.java
deleted file mode 100644
index 44fee4e18..000000000
--- a/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetProxy.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetWrapper.java b/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetWrapper.java
new file mode 100644
index 000000000..8fe60119b
--- /dev/null
+++ b/app/src/main/java/ru/vtosters/lite/ui/vkui/ModalBottomSheetWrapper.java
@@ -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;
+ }
+}
diff --git a/smali/AndroidManifest.xml b/smali/AndroidManifest.xml
index 8bd0404e5..c11c15108 100644
--- a/smali/AndroidManifest.xml
+++ b/smali/AndroidManifest.xml
@@ -75,6 +75,7 @@
+