From 51fbf6b8399c5aa215563e3735f98fc8ff740c75 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Tue, 27 Jul 2021 07:01:13 +0200 Subject: [PATCH] [android] Game data installation screen --- android-project/app/build.gradle | 1 + .../app/src/main/AndroidManifest.xml | 6 + .../diasurgical/devilutionx/DataActivity.java | 119 ++++++++++++++++++ .../devilutionx/DevilutionXSDLActivity.java | 51 +++----- .../app/src/main/res/layout/activity_data.xml | 78 ++++++++++++ .../app/src/main/res/values/colors.xml | 7 ++ .../app/src/main/res/values/strings.xml | 14 ++- .../app/src/main/res/values/themes.xml | 9 ++ 8 files changed, 249 insertions(+), 36 deletions(-) create mode 100644 android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java create mode 100644 android-project/app/src/main/res/layout/activity_data.xml create mode 100644 android-project/app/src/main/res/values/colors.xml create mode 100644 android-project/app/src/main/res/values/themes.xml diff --git a/android-project/app/build.gradle b/android-project/app/build.gradle index 96a6c1484..5f3230077 100644 --- a/android-project/app/build.gradle +++ b/android-project/app/build.gradle @@ -61,4 +61,5 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support.constraint:constraint-layout:2.0.4' } diff --git a/android-project/app/src/main/AndroidManifest.xml b/android-project/app/src/main/AndroidManifest.xml index 80f5f96b8..d50f041d4 100644 --- a/android-project/app/src/main/AndroidManifest.xml +++ b/android-project/app/src/main/AndroidManifest.xml @@ -35,6 +35,8 @@ + + --> + + + diff --git a/android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java b/android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java new file mode 100644 index 000000000..66c5be705 --- /dev/null +++ b/android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java @@ -0,0 +1,119 @@ +package org.diasurgical.devilutionx; + +import android.app.DownloadManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.Cursor; +import android.net.Uri; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.text.method.LinkMovementMethod; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.File; + +public class DataActivity extends AppCompatActivity { + private String externalDir; + private DownloadReceiver mReceiver; + private boolean isDownloading = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + externalDir = getExternalFilesDir(null).getAbsolutePath(); + + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_data); + + ((TextView) findViewById(R.id.full_guide)).setMovementMethod(LinkMovementMethod.getInstance()); + ((TextView) findViewById(R.id.online_guide)).setMovementMethod(LinkMovementMethod.getInstance()); + } + + protected void onResume() { + super.onResume(); + startGame(); + } + + public void startGame(View view) { + startGame(); + } + + private void startGame() { + if (missingGameData()) { + Toast toast = Toast.makeText(getApplicationContext(), "Game data missing", Toast.LENGTH_SHORT); + toast.show(); + return; + } + + Intent intent = new Intent(this, DevilutionXSDLActivity.class); + startActivity(intent); + this.finish(); + } + + /** + * Check if the game data is present + */ + private boolean missingGameData() { + File fileLower = new File(externalDir + "/diabdat.mpq"); + File fileUpper = new File(externalDir + "/DIABDAT.MPQ"); + File spawnFile = new File(externalDir + "/spawn.mpq"); + + return !fileUpper.exists() && !fileLower.exists() && (!spawnFile.exists() || isDownloading); + } + + /** + * Start downloading the shareware + */ + public void sendDownloadRequest(View view) { + String url = "https://github.com/d07RiV/diabloweb/raw/3a5a51e84d5dab3cfd4fef661c46977b091aaa9c/spawn.mpq"; + String fileName = "spawn.mpq"; + + DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)) + .setTitle(fileName) + .setDescription("Diablo Shareware Data") + .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); + + request.setDestinationInExternalFilesDir(this, null, fileName); + + DownloadManager downloadManager = (DownloadManager)this.getSystemService(Context.DOWNLOAD_SERVICE); + downloadManager.enqueue(request); + + if (mReceiver == null) + mReceiver = new DownloadReceiver(); + registerReceiver(mReceiver, new IntentFilter("android.intent.action.DOWNLOAD_COMPLETE")); + + isDownloading = true; + view.setEnabled(false); + + Toast toast = Toast.makeText(getApplicationContext(), "Download started", Toast.LENGTH_SHORT); + toast.show(); + } + + /** + * Start game when download finishes + */ + private class DownloadReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + isDownloading = false; + + long receivedID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L); + DownloadManager mgr = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); + + DownloadManager.Query query = new DownloadManager.Query(); + query.setFilterById(receivedID); + Cursor cur = mgr.query(query); + int index = cur.getColumnIndex(DownloadManager.COLUMN_STATUS); + if (cur.moveToFirst()) { + if (cur.getInt(index) == DownloadManager.STATUS_SUCCESSFUL) { + startGame(); + } + } + cur.close(); + findViewById(R.id.download_button).setEnabled(true); + } + } +} diff --git a/android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java b/android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java index a5ce0c51f..7627785c4 100644 --- a/android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java +++ b/android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java @@ -1,13 +1,12 @@ package org.diasurgical.devilutionx; import android.Manifest; -import android.app.AlertDialog; -import android.content.SharedPreferences; +import android.annotation.SuppressLint; +import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; import org.libsdl.app.SDLActivity; @@ -20,8 +19,6 @@ import java.io.InputStream; import java.io.OutputStream; public class DevilutionXSDLActivity extends SDLActivity { - private SharedPreferences mPrefs; - final private String shouldShowInstallationGuidePref = "shouldShowInstallationGuide"; private String externalDir; protected void onCreate(Bundle savedInstanceState) { @@ -29,44 +26,28 @@ public class DevilutionXSDLActivity extends SDLActivity { migrateAppData(); - if (shouldShowInstallationGuide()) { - showInstallationGuide(); - } - super.onCreate(savedInstanceState); } /** - * Check if this is the first time the app is run and the full game data is not already present + * On app launch make sure the game data is present */ - private boolean shouldShowInstallationGuide() { - mPrefs = PreferenceManager.getDefaultSharedPreferences(this); - return mPrefs.getBoolean(shouldShowInstallationGuidePref, !hasFullGameData()); + protected void onStart() { + super.onStart(); + + if (missingGameData()) { + Intent intent = new Intent(this, DataActivity.class); + startActivity(intent); + this.finish(); + } } - private boolean hasFullGameData() { + private boolean missingGameData() { File fileLower = new File(externalDir + "/diabdat.mpq"); File fileUpper = new File(externalDir + "/DIABDAT.MPQ"); + File spawnFile = new File(externalDir + "/spawn.mpq"); - return fileUpper.exists() || fileLower.exists(); - } - - private void installationGuideShown() { - SharedPreferences.Editor editor = mPrefs.edit(); - editor.putBoolean(shouldShowInstallationGuidePref, false); - editor.apply(); - } - - private void showInstallationGuide() { - String message = "To play the full version you must place DIABDAT.MPQ from the original game in Android" - + externalDir.split("/Android")[1] - + ".\n\nIf you don't have the original game then you can buy Diablo from GOG.com."; - new AlertDialog.Builder(this) - .setTitle("Shareware version") - .setPositiveButton("OK", null) - .setMessage(message) - .show(); - installationGuideShown(); + return !fileUpper.exists() && !fileLower.exists() && !spawnFile.exists(); } private boolean copyFile(File src, File dst) { @@ -106,6 +87,7 @@ public class DevilutionXSDLActivity extends SDLActivity { File newPath = new File(externalDir + "/" + file.getName()); if (newPath.exists()) { if (file.canWrite()) { + //noinspection ResultOfMethodCallIgnored file.delete(); } return; @@ -115,6 +97,7 @@ public class DevilutionXSDLActivity extends SDLActivity { } if (!file.renameTo(newPath)) { if (copyFile(file, newPath) && file.canWrite()) { + //noinspection ResultOfMethodCallIgnored file.delete(); } } @@ -123,6 +106,8 @@ public class DevilutionXSDLActivity extends SDLActivity { /** * This can be removed Nov 2021 and Google will no longer permit access to the old folder from that point on */ + @SuppressWarnings("deprecation") + @SuppressLint("SdCardPath") private void migrateAppData() { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { if (PackageManager.PERMISSION_GRANTED != checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) { diff --git a/android-project/app/src/main/res/layout/activity_data.xml b/android-project/app/src/main/res/layout/activity_data.xml new file mode 100644 index 000000000..6d87a0578 --- /dev/null +++ b/android-project/app/src/main/res/layout/activity_data.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + +