doukutsu-rs/app/app/src/main/java/io/github/doukutsu_rs/DownloadActivity.java

202 lines
7.1 KiB
Java

package io.github.doukutsu_rs;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class DownloadActivity extends AppCompatActivity {
private TextView txtProgress;
private ProgressBar progressBar;
private DownloadThread downloadThread;
private String basePath;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
txtProgress = findViewById(R.id.txtProgress);
progressBar = findViewById(R.id.progressBar);
ActivityUtils.hideSystemBars(this);
basePath = getFilesDir().getAbsolutePath() + "/";
downloadThread = new DownloadThread();
downloadThread.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
downloadThread.interrupt();
}
private class DownloadThread extends Thread {
private final ArrayList<DownloadEntry> urls = new ArrayList<>();
private final ArrayList<String> filesWhitelist = new ArrayList<>();
@Override
public void run() {
this.filesWhitelist.add("data/");
this.filesWhitelist.add("Doukutsu.exe");
// DON'T SET `true` VALUE FOR TRANSLATIONS
this.urls.add(new DownloadEntry(R.string.download_entries_base, "https://www.cavestory.org/downloads/cavestoryen.zip", true));
for (DownloadEntry entry : this.urls) {
this.download(entry);
}
}
private void download(DownloadEntry downloadEntry) {
HttpURLConnection connection = null;
try {
URL url = new URL(downloadEntry.url);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IllegalStateException(getString(R.string.download_status_error_http, connection.getResponseCode()));
}
int fileLength = connection.getContentLength();
if (fileLength == 0) {
handler.post(() -> progressBar.setIndeterminate(true));
}
byte[] zipFile;
{
InputStream input = new BufferedInputStream(connection.getInputStream());
ByteArrayOutputStream output = new ByteArrayOutputStream();
int downloadedLast = 0;
int downloaded = 0;
byte[] buffer = new byte[4096];
int count;
long last = System.currentTimeMillis();
while ((count = input.read(buffer)) != -1) {
downloaded += count;
output.write(buffer, 0, count);
long now = System.currentTimeMillis();
if (last + 1000 >= now) {
int speed = (int) ((downloaded - downloadedLast) / 1024.0);
String text = (fileLength > 0)
? getString(R.string.download_status_downloading, downloadEntry.name, downloaded * 100 / fileLength, downloaded / 1024, fileLength / 1024, speed)
: getString(R.string.download_status_downloading_null, downloadEntry.name, downloaded / 1024, speed);
handler.post(() -> txtProgress.setText(text));
downloadedLast = downloaded;
last = now;
}
}
output.flush();
zipFile = output.toByteArray();
output.close();
}
new File(basePath).mkdirs();
this.unpack(zipFile, downloadEntry.isBase);
handler.post(() -> txtProgress.setText(getString(R.string.download_status_done)));
handler.post(() -> {
Intent intent = new Intent(DownloadActivity.this, GameActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
DownloadActivity.this.finish();
});
} catch (Exception e) {
handler.post(() -> {
if (txtProgress != null)
txtProgress.setText(e.getMessage());
});
e.printStackTrace();
} finally {
if (connection != null) connection.disconnect();
}
}
private void unpack(byte[] zipFile, boolean isBase) throws IOException {
ZipInputStream in = new ZipInputStream(new ByteArrayInputStream(zipFile));
ZipEntry entry;
byte[] buffer = new byte[4096];
while ((entry = in.getNextEntry()) != null) {
String entryName = entry.getName();
// strip prefix
if (entryName.startsWith("CaveStory/")) {
entryName = entryName.substring("CaveStory/".length());
}
if (!this.entryInWhitelist(entryName)) {
continue;
}
final String s = entryName;
handler.post(() -> txtProgress.setText(
getString(R.string.download_status_unpacking, s)
));
if (entry.isDirectory()) {
new File(basePath + entryName).mkdirs();
} else {
try (FileOutputStream fos = new FileOutputStream(basePath + entryName)) {
int count;
while ((count = in.read(buffer)) != -1) {
fos.write(buffer, 0, count);
}
}
}
in.closeEntry();
}
}
private boolean entryInWhitelist(String entry) {
for (String file : this.filesWhitelist) {
if (entry.startsWith(file)) {
return true;
}
}
return false;
}
}
private class DownloadEntry {
public String name; //e.g. "Polish translation", "Base data files"
public String url;
public boolean isBase = false;
DownloadEntry(String name, String url, boolean isBase) {
this.name = name;
this.url = url;
this.isBase = isBase;
}
DownloadEntry(int name, String url, boolean isBase) {
this.name = getString(name);
this.url = url;
this.isBase = isBase;
}
}
}