You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
330 lines
14 KiB
Java
330 lines
14 KiB
Java
package com.fox2code.mmm;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
|
|
import androidx.core.content.FileProvider;
|
|
|
|
import com.fox2code.foxcompat.app.FoxActivity;
|
|
import com.fox2code.mmm.utils.io.Http;
|
|
import com.google.android.material.button.MaterialButton;
|
|
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
|
import com.google.android.material.textview.MaterialTextView;
|
|
|
|
import org.json.JSONArray;
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.util.Objects;
|
|
|
|
import timber.log.Timber;
|
|
|
|
@SuppressWarnings("UnnecessaryReturnStatement")
|
|
public class UpdateActivity extends FoxActivity {
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.activity_update);
|
|
// Get the progress bar and make it indeterminate for now
|
|
LinearProgressIndicator progressIndicator = findViewById(R.id.update_progress);
|
|
progressIndicator.setIndeterminate(true);
|
|
// get status text view
|
|
MaterialTextView statusTextView = findViewById(R.id.update_progress_text);
|
|
// set status text to please wait
|
|
statusTextView.setText(R.string.please_wait);
|
|
// for debug builds, set update_debug_warning to visible and return
|
|
/**if (BuildConfig.DEBUG) {
|
|
findViewById(R.id.update_debug_warning).setVisibility(MaterialTextView.VISIBLE);
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(0, false);
|
|
statusTextView.setVisibility(MaterialTextView.INVISIBLE);
|
|
return;
|
|
}*/
|
|
new Thread(() -> {
|
|
// Now, parse the intent
|
|
String extras = getIntent().getAction();
|
|
// if extras is null, then we are in a bad state or user launched the activity manually
|
|
if (extras == null) {
|
|
runOnUiThread(() -> {
|
|
// set status text to error
|
|
statusTextView.setText(R.string.error_no_extras);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(0, false);
|
|
});
|
|
return;
|
|
}
|
|
|
|
// get action
|
|
ACTIONS action = ACTIONS.valueOf(extras);
|
|
// if action is null, then we are in a bad state or user launched the activity manually
|
|
if (Objects.isNull(action)) {
|
|
runOnUiThread(() -> {
|
|
// set status text to error
|
|
statusTextView.setText(R.string.error_no_action);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(0, false);
|
|
});
|
|
// return
|
|
return;
|
|
}
|
|
|
|
// For check action, we need to check if there is an update using the AppUpdateManager.peekShouldUpdate()
|
|
if (action == ACTIONS.CHECK) {
|
|
checkForUpdate();
|
|
} else if (action == ACTIONS.DOWNLOAD) {
|
|
try {
|
|
downloadUpdate();
|
|
} catch (
|
|
JSONException e) {
|
|
e.printStackTrace();
|
|
runOnUiThread(() -> {
|
|
// set status text to error
|
|
statusTextView.setText(R.string.error_download_update);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
});
|
|
}
|
|
} else if (action == ACTIONS.INSTALL) {
|
|
// ensure path was passed and points to a file within our cache directory
|
|
String path = getIntent().getStringExtra("path");
|
|
if (path == null) {
|
|
runOnUiThread(() -> {
|
|
// set status text to error
|
|
statusTextView.setText(R.string.no_file_found);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(0, false);
|
|
});
|
|
return;
|
|
}
|
|
File file = new File(path);
|
|
if (!file.exists()) {
|
|
runOnUiThread(() -> {
|
|
// set status text to error
|
|
statusTextView.setText(R.string.no_file_found);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(0, false);
|
|
});
|
|
// return
|
|
return;
|
|
}
|
|
if (!Objects.equals(file.getParentFile(), getCacheDir())) {
|
|
// set status text to error
|
|
runOnUiThread(() -> {
|
|
statusTextView.setText(R.string.no_file_found);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(0, false);
|
|
});
|
|
// return
|
|
return;
|
|
}
|
|
// set status text to installing
|
|
statusTextView.setText(R.string.installing_update);
|
|
// set progress bar to indeterminate
|
|
progressIndicator.setIndeterminate(true);
|
|
// install update
|
|
installUpdate(file);
|
|
}
|
|
|
|
}).start();
|
|
}
|
|
|
|
public void checkForUpdate() {
|
|
LinearProgressIndicator progressIndicator = findViewById(R.id.update_progress);
|
|
progressIndicator.setIndeterminate(true);
|
|
// get status text view
|
|
MaterialTextView statusTextView = findViewById(R.id.update_progress_text);
|
|
// set status text to checking for update
|
|
statusTextView.setText(R.string.checking_for_update);
|
|
// set progress bar to indeterminate
|
|
progressIndicator.setIndeterminate(true);
|
|
// check for update
|
|
boolean shouldUpdate = AppUpdateManager.getAppUpdateManager().peekShouldUpdate();
|
|
// if shouldUpdate is true, then we have an update
|
|
if (shouldUpdate) {
|
|
// set status text to update available
|
|
statusTextView.setText(R.string.update_available);
|
|
// set button text to download
|
|
MaterialButton button = findViewById(R.id.update_button);
|
|
button.setText(R.string.download_update);
|
|
// return
|
|
} else {
|
|
// set status text to no update available
|
|
statusTextView.setText(R.string.no_update_available);
|
|
// set progress bar to error
|
|
// return
|
|
}
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
return;
|
|
}
|
|
|
|
public void downloadUpdate() throws JSONException {
|
|
LinearProgressIndicator progressIndicator = findViewById(R.id.update_progress);
|
|
progressIndicator.setIndeterminate(true);
|
|
// get status text view
|
|
MaterialTextView statusTextView = findViewById(R.id.update_progress_text);
|
|
byte[] lastestJSON = new byte[0];
|
|
try {
|
|
lastestJSON = Http.doHttpGet(AppUpdateManager.RELEASES_API_URL, false);
|
|
} catch (
|
|
Exception e) {
|
|
// when logging, REMOVE the json from the log
|
|
String msg = e.getMessage();
|
|
// remove everything from the first { to the last }
|
|
msg = Objects.requireNonNull(msg).substring(0, msg.indexOf("{")) + msg.substring(msg.lastIndexOf("}") + 1);
|
|
Timber.e(msg);
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
statusTextView.setText(R.string.error_download_update);
|
|
}
|
|
// convert to JSON
|
|
JSONObject latestJSON = new JSONObject(new String(lastestJSON));
|
|
// we already know that there is an update, so we can get the latest version of our architecture. We're going to have to iterate through the assets to find the one we want
|
|
JSONArray assets = latestJSON.getJSONArray("assets");
|
|
// get the asset we want
|
|
JSONObject asset = null;
|
|
// iterate through assets until we find the one that contains Build.SUPPORTED_ABIS[0]
|
|
while (Objects.isNull(asset)) {
|
|
for (int i = 0; i < assets.length(); i++) {
|
|
JSONObject asset1 = assets.getJSONObject(i);
|
|
if (asset1.getString("name").contains(Build.SUPPORTED_ABIS[0])) {
|
|
asset = asset1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// if asset is null, then we are in a bad state
|
|
if (Objects.isNull(asset)) {
|
|
// set status text to error
|
|
statusTextView.setText(R.string.error_no_asset);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
// return
|
|
return;
|
|
}
|
|
// get the download url
|
|
String downloadUrl = Objects.requireNonNull(asset).getString("browser_download_url");
|
|
// get the download size
|
|
long downloadSize = asset.getLong("size");
|
|
runOnUiThread(() -> {
|
|
// set status text to downloading update
|
|
statusTextView.setText(getString(R.string.downloading_update, 0));
|
|
// set progress bar to 0
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(0, false);
|
|
});
|
|
// download the update
|
|
byte[] update = new byte[0];
|
|
try {
|
|
update = Http.doHttpGet(downloadUrl, (downloaded, total, done) -> runOnUiThread(() -> {
|
|
// update progress bar
|
|
progressIndicator.setProgressCompat((int) (((float) downloaded / (float) total) * 100), true);
|
|
// update status text
|
|
statusTextView.setText(getString(R.string.downloading_update, (int) (((float) downloaded / (float) total) * 100)));
|
|
}));
|
|
} catch (
|
|
Exception e) {
|
|
e.printStackTrace();
|
|
runOnUiThread(() -> {
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
statusTextView.setText(R.string.error_download_update);
|
|
});
|
|
}
|
|
// if update is null, then we are in a bad state
|
|
if (Objects.isNull(update)) {
|
|
runOnUiThread(() -> {
|
|
// set status text to error
|
|
statusTextView.setText(R.string.error_download_update);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
});
|
|
// return
|
|
return;
|
|
}
|
|
// if update is not the same size as the download size, then we are in a bad state
|
|
if (update.length != downloadSize) {
|
|
runOnUiThread(() -> {
|
|
// set status text to error
|
|
statusTextView.setText(R.string.error_download_update);
|
|
// set progress bar to error
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
});
|
|
// return
|
|
return;
|
|
}
|
|
// set status text to installing update
|
|
runOnUiThread(() -> {
|
|
statusTextView.setText(R.string.installing_update);
|
|
// set progress bar to 100
|
|
progressIndicator.setIndeterminate(true);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
});
|
|
// save the update to the cache
|
|
File updateFile = null;
|
|
try {
|
|
updateFile = new File(getCacheDir(), "update.apk");
|
|
FileOutputStream fileOutputStream = new FileOutputStream(updateFile);
|
|
fileOutputStream.write(update);
|
|
fileOutputStream.close();
|
|
} catch (
|
|
IOException e) {
|
|
e.printStackTrace();
|
|
runOnUiThread(() -> {
|
|
progressIndicator.setIndeterminate(false);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
statusTextView.setText(R.string.error_download_update);
|
|
});
|
|
}
|
|
// install the update
|
|
installUpdate(updateFile);
|
|
// return
|
|
return;
|
|
}
|
|
|
|
@SuppressLint("RestrictedApi")
|
|
private void installUpdate(File updateFile) {
|
|
// get status text view
|
|
runOnUiThread(() -> {
|
|
MaterialTextView statusTextView = findViewById(R.id.update_progress_text);
|
|
// set status text to installing update
|
|
statusTextView.setText(R.string.installing_update);
|
|
// set progress bar to 100
|
|
LinearProgressIndicator progressIndicator = findViewById(R.id.update_progress);
|
|
progressIndicator.setIndeterminate(true);
|
|
progressIndicator.setProgressCompat(100, false);
|
|
});
|
|
// request install permissions
|
|
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
|
|
Context context = getApplicationContext();
|
|
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".file-provider", updateFile);
|
|
intent.setData(uri);
|
|
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
startActivity(intent);
|
|
// return
|
|
return;
|
|
}
|
|
|
|
public enum ACTIONS {
|
|
// action can be CHECK, DOWNLOAD, INSTALL
|
|
CHECK, DOWNLOAD, INSTALL
|
|
}
|
|
} |