final changes

added apk downloading and installing features, bottomshit wrapper with mirroring
This commit is contained in:
Vologhat
2022-06-15 21:29:09 +03:00
parent 986ec2987c
commit 6e3716fe01
6 changed files with 246 additions and 58 deletions
@@ -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);
}
}
@@ -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();
}
}
@@ -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();
});
}
}
@@ -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
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"/>