diff --git a/.gitignore b/.gitignore
index a95ae19..7bc2fc0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,10 @@ DEADJOE
.#*
*.jar
*.zip
+*.aab
*.apk
+*.jks
+*.keystore
bin/
gen/
bin/*
@@ -18,3 +21,13 @@ build.xml
assets/build.properties
.settings/
.settings/*
+*.iml
+.gradle
+/local.properties
+/.idea
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
deleted file mode 100644
index be1e3a5..0000000
--- a/AndroidManifest.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..7f364bb
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,38 @@
+plugins {
+ alias(libs.plugins.android.application)
+}
+
+android {
+ namespace 'de.onyxbits.textfiction'
+ compileSdk 35
+
+ defaultConfig {
+ applicationId "de.onyxbits.textfiction"
+ minSdk 24
+ targetSdk 33
+ versionCode 12
+ versionName "3.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
+ }
+}
+
+dependencies {
+
+ implementation libs.appcompat
+ implementation libs.material
+ testImplementation libs.junit
+ androidTestImplementation libs.ext.junit
+ androidTestImplementation libs.espresso.core
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b45cf76
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/de/onyxbits/textfiction/AppRater.java b/app/src/main/java/de/onyxbits/textfiction/AppRater.java
similarity index 100%
rename from src/de/onyxbits/textfiction/AppRater.java
rename to app/src/main/java/de/onyxbits/textfiction/AppRater.java
diff --git a/src/de/onyxbits/textfiction/FileUtil.java b/app/src/main/java/de/onyxbits/textfiction/FileUtil.java
similarity index 78%
rename from src/de/onyxbits/textfiction/FileUtil.java
rename to app/src/main/java/de/onyxbits/textfiction/FileUtil.java
index 3996083..6242d3b 100644
--- a/src/de/onyxbits/textfiction/FileUtil.java
+++ b/app/src/main/java/de/onyxbits/textfiction/FileUtil.java
@@ -10,7 +10,11 @@
import java.util.Arrays;
import java.util.Comparator;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
import android.os.Environment;
+import android.provider.OpenableColumns;
public class FileUtil implements Comparator {
@@ -43,7 +47,8 @@ public class FileUtil implements Comparator {
* Just make sure we got all of our directories.
*/
static {
- File root = Environment.getExternalStorageDirectory();
+ // File root = Environment.getExternalStorageDirectory();
+ File root = MainActivity.appContext().getExternalFilesDir(null);
library = new File(new File(root, HOMEDIR), GAMEDIR);
saves = new File(new File(root, HOMEDIR), SAVEDIR);
data = new File(new File(root, HOMEDIR), DATADIR);
@@ -115,11 +120,32 @@ public FileUtil() {
* @throws IOException
* if something goes wrong
*/
- public static void importGame(File src) throws IOException {
+ public static void importGame(Uri src) throws IOException {
ensureDirs();
- File dst = new File(library, src.getName());
+ FileInputStream fin;
+ File dst;
+ if (src != null && src.getScheme().equals(ContentResolver.SCHEME_FILE)) {
+ File from = new File(src.getPath());
+ dst = new File(library, from.getName());
+ fin = new FileInputStream(from);
+ } else if(src != null && src.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
+ Cursor uCursor = MainActivity.appContext().getContentResolver().query(src, null, null, null, null);
+ String fName = "";
+ if (uCursor != null && uCursor.moveToFirst()) {
+ int nameIndex = uCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ int sizeIndex = uCursor.getColumnIndex(OpenableColumns.SIZE);
+ fName = uCursor.getString(nameIndex);
+ }
+ assert uCursor != null;
+ uCursor.close();
+ dst = new File(library, fName);
+ fin = new FileInputStream(MainActivity.appContext().getContentResolver().openFileDescriptor(src, "r").getFileDescriptor());
+ }
+ else {
+ return;
+ }
byte[] buf = new byte[1024];
- FileInputStream fin = new FileInputStream(src);
+ //FileInputStream fin = new FileInputStream(from);
FileOutputStream fout = new FileOutputStream(dst);
int len;
diff --git a/src/de/onyxbits/textfiction/GameActivity.java b/app/src/main/java/de/onyxbits/textfiction/GameActivity.java
similarity index 89%
rename from src/de/onyxbits/textfiction/GameActivity.java
rename to app/src/main/java/de/onyxbits/textfiction/GameActivity.java
index 09dfda7..1eae3f0 100644
--- a/src/de/onyxbits/textfiction/GameActivity.java
+++ b/app/src/main/java/de/onyxbits/textfiction/GameActivity.java
@@ -40,9 +40,9 @@
import android.widget.ViewFlipper;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.NavUtils;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.core.app.NavUtils;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.AlertDialog;
@@ -72,6 +72,7 @@ public class GameActivity extends FragmentActivity implements DialogInterface.On
* of the game via this extra.
*/
public static final String LOADFILE = "loadfile";
+ // public static final String FILENAME = "filename";
/**
* How many items to keep in the messagebuffer at most. Note: this should be
@@ -127,6 +128,7 @@ public class GameActivity extends FragmentActivity implements DialogInterface.On
/**
* The game playing in this activity
*/
+ // private Uri storyFile;
private File storyFile;
/**
@@ -308,62 +310,52 @@ public boolean onPrepareOptionsMenu(Menu menu) {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.mi_flip_view: {
- flipView(windowFlipper.getCurrentView() != storyBoard);
- return true;
- }
- case R.id.mi_save: {
- pendingAction = PENDING_SAVE;
- saveName = new EditText(this);
- saveName.setSingleLine(true);
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.title_save_game).setPositiveButton(android.R.string.ok, this)
- .setView(saveName).show();
- return true;
- }
- case R.id.mi_restore: {
- String[] sg = FileUtil.listSaveName(storyFile);
- if (sg.length > 0) {
- pendingAction = PENDING_RESTORE;
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.title_restore_game).setItems(sg, this).show();
- }
- else {
- Toast.makeText(this, R.string.msg_no_savegames, Toast.LENGTH_SHORT).show();
- }
- return true;
- }
-
- case R.id.mi_clear_log: {
- retainerFragment.messageBuffer.clear();
- messages.notifyDataSetChanged();
- return true;
- }
- case R.id.mi_help: {
- MainActivity.openUri(this, Uri.parse(getString(R.string.url_help)));
- return true;
- }
- case R.id.mi_restart: {
- pendingAction = PENDING_RESTART;
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.title_please_confirm).setMessage(R.string.msg_really_restart)
- .setPositiveButton(android.R.string.yes, this)
- .setNegativeButton(android.R.string.no, this).show();
- return true;
- }
-
- case android.R.id.home:
- // This ID represents the Home or Up button. In the case of this
- // activity, the Up button is shown. Use NavUtils to allow users
- // to navigate up one level in the application structure. For
- // more details, see the Navigation pattern on Android Design:
- //
- // http://developer.android.com/design/patterns/navigation.html#up-vs-back
- //
- NavUtils.navigateUpFromSameTask(this);
- return true;
- }
+ int itemId = item.getItemId();
+ if (itemId == R.id.mi_flip_view) {
+ flipView(windowFlipper.getCurrentView() != storyBoard);
+ return true;
+ } else if (itemId == R.id.mi_save) {
+ pendingAction = PENDING_SAVE;
+ saveName = new EditText(this);
+ saveName.setSingleLine(true);
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.title_save_game).setPositiveButton(android.R.string.ok, this)
+ .setView(saveName).show();
+ return true;
+ } else if (itemId == R.id.mi_restore) {
+ String[] sg = FileUtil.listSaveName(storyFile);
+ if (sg.length > 0) {
+ pendingAction = PENDING_RESTORE;
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.title_restore_game).setItems(sg, this).show();
+ } else {
+ Toast.makeText(this, R.string.msg_no_savegames, Toast.LENGTH_SHORT).show();
+ }
+ return true;
+ } else if (itemId == R.id.mi_clear_log) {
+ retainerFragment.messageBuffer.clear();
+ messages.notifyDataSetChanged();
+ return true;
+ } else if (itemId == R.id.mi_help) {
+ MainActivity.openUri(this, Uri.parse(getString(R.string.url_help)));
+ return true;
+ } else if (itemId == R.id.mi_restart) {
+ pendingAction = PENDING_RESTART;
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.title_please_confirm).setMessage(R.string.msg_really_restart)
+ .setPositiveButton(android.R.string.yes, this)
+ .setNegativeButton(android.R.string.no, this).show();
+ return true;
+ } else if (itemId == android.R.id.home) {// This ID represents the Home or Up button. In the case of this
+ // activity, the Up button is shown. Use NavUtils to allow users
+ // to navigate up one level in the application structure. For
+ // more details, see the Navigation pattern on Android Design:
+ //
+ // http://developer.android.com/design/patterns/navigation.html#up-vs-back
+ //
+ NavUtils.navigateUpFromSameTask(this);
+ return true;
+ }
return super.onOptionsItemSelected(item);
}
@@ -539,9 +531,9 @@ private void flipView(boolean showstory) {
if (showstory) {
if (now != storyBoard) {
- windowFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.animator.slide_in_right));
+ windowFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_in_right));
windowFlipper
- .setOutAnimation(AnimationUtils.loadAnimation(this, R.animator.slide_out_left));
+ .setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_out_left));
windowFlipper.showPrevious();
}
}
diff --git a/src/de/onyxbits/textfiction/ImportTask.java b/app/src/main/java/de/onyxbits/textfiction/ImportTask.java
similarity index 86%
rename from src/de/onyxbits/textfiction/ImportTask.java
rename to app/src/main/java/de/onyxbits/textfiction/ImportTask.java
index de4f994..aff833b 100644
--- a/src/de/onyxbits/textfiction/ImportTask.java
+++ b/app/src/main/java/de/onyxbits/textfiction/ImportTask.java
@@ -1,16 +1,23 @@
package de.onyxbits.textfiction;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FilenameFilter;
import java.util.Arrays;
+import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Environment;
+//import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
+import android.app.Activity;
+
+import static androidx.core.app.ActivityCompat.startActivityForResult;
/**
* Helper task for the LibraryFragment that takes care of copying games from the
@@ -28,7 +35,7 @@ class ImportTask extends AsyncTask