Skip to content
This repository was archived by the owner on Mar 12, 2026. It is now read-only.

Commit a97dd6d

Browse files
committed
Fixed errors related to accessing resources
1 parent 8e4cde3 commit a97dd6d

File tree

12 files changed

+159
-82
lines changed

12 files changed

+159
-82
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
android:allowBackup="false"
2323
android:supportsRtl="true"
2424
android:fullBackupContent="false"
25-
android:requestLegacyExternalStorage="true"
2625
android:dataExtractionRules="@xml/data_extraction_rules"
2726
tools:targetApi="s">
2827

app/src/main/java/org/qp/android/QuestPlayerApplication.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import android.app.NotificationManager;
66
import android.content.Context;
77
import android.os.Build;
8+
import android.util.Log;
89

10+
import androidx.annotation.NonNull;
911
import androidx.documentfile.provider.DocumentFile;
1012

1113
import org.qp.android.model.libQP.LibQpProxy;
@@ -30,13 +32,18 @@ public class QuestPlayerApplication extends Application {
3032
private final LibQpProxyImpl libQspProxy = new LibQpProxyImpl(this, gameContentResolver, htmlProcessor, audioPlayer);
3133

3234
private DocumentFile customRootDir;
35+
private DocumentFile currentGameDir;
3336

3437
@Override
3538
public void onCreate() {
3639
super.onCreate();
3740
createNotificationChannels();
3841
}
3942

43+
public void setCurrentGameDir(DocumentFile currentGameDir) {
44+
this.currentGameDir = currentGameDir;
45+
}
46+
4047
public void setCustomRootFolder(DocumentFile customRootDir) {
4148
this.customRootDir = customRootDir;
4249
}
@@ -46,6 +53,7 @@ public GameContentResolver getGameContentResolver() {
4653
}
4754

4855
public HtmlProcessor getHtmlProcessor() {
56+
htmlProcessor.setContext(this);
4957
return htmlProcessor;
5058
}
5159

@@ -61,6 +69,10 @@ public DocumentFile getCustomRootDir() {
6169
return customRootDir;
6270
}
6371

72+
public DocumentFile getCurrentGameDir() {
73+
return currentGameDir;
74+
}
75+
6476
public void createNotificationChannels() {
6577
var notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
6678
var importance = NotificationManager.IMPORTANCE_LOW;
@@ -73,4 +85,44 @@ public void createNotificationChannels() {
7385
notificationManager.createNotificationChannel(channel);
7486

7587
}
88+
89+
public DocumentFile fromFullPath(@NonNull String fullPath) {
90+
var findDir = getCustomRootDir();
91+
var nameGameDir = currentGameDir.getName();
92+
93+
var index = fullPath.lastIndexOf(nameGameDir);
94+
var simplePath = fullPath.substring(index);
95+
var pathToSoundSegments = simplePath.split("/");
96+
97+
for (var segment : pathToSoundSegments) {
98+
if (segment.isEmpty()) {
99+
continue;
100+
}
101+
findDir = findDir.findFile(segment);
102+
if (findDir == null) {
103+
break;
104+
}
105+
}
106+
107+
return findDir;
108+
}
109+
110+
public DocumentFile fromRelativePath(@NonNull String relPath) {
111+
var pathToFileSegments = relPath.split("/");
112+
var relFile = currentGameDir;
113+
114+
for (var segment : pathToFileSegments) {
115+
if (segment.isEmpty()) {
116+
continue;
117+
}
118+
relFile = relFile.findFile(segment);
119+
if (relFile == null) {
120+
break;
121+
}
122+
}
123+
124+
Log.d(this.getClass().getSimpleName() , relPath);
125+
126+
return relFile;
127+
}
76128
}

app/src/main/java/org/qp/android/helpers/Bind.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@
99

1010
import org.qp.android.R;
1111

12-
import java.io.File;
13-
1412
public class Bind {
1513
@BindingAdapter({"imageUrl"})
1614
public static void loadImage(ImageView view, String imageUrl) {
1715
if (imageUrl != null && !imageUrl.isEmpty()) {
1816
if (view.getId() == R.id.imageBox) {
1917
Picasso.get()
20-
.load(new File(imageUrl))
18+
.load(imageUrl)
2119
.into(view);
2220
} else {
2321
Picasso.get()

app/src/main/java/org/qp/android/helpers/utils/FileUtil.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.qp.android.helpers.utils;
22

33
import android.content.Context;
4+
import android.net.Uri;
45
import android.util.Log;
56

67
import androidx.annotation.NonNull;
@@ -15,7 +16,6 @@
1516
import java.io.BufferedReader;
1617
import java.io.ByteArrayOutputStream;
1718
import java.io.File;
18-
import java.io.FileInputStream;
1919
import java.io.IOException;
2020
import java.io.InputStreamReader;
2121
import java.text.DecimalFormat;
@@ -184,15 +184,16 @@ public static <T> void deleteDirectory(T dir) {
184184
}
185185

186186
@Nullable
187-
public static byte[] getFileContents(String path) {
188-
var file = new File(path);
189-
try (var in = new FileInputStream(file)) {
187+
public static byte[] getFileContents(@NonNull Context context ,
188+
@NonNull Uri uriContent) {
189+
var resolver = context.getContentResolver();
190+
try (var in = resolver.openInputStream(uriContent)) {
190191
try (var out = new ByteArrayOutputStream()) {
191192
StreamUtil.copy(in , out);
192193
return out.toByteArray();
193194
}
194195
} catch (IOException ex) {
195-
Log.e(TAG , "Error reading file: " + path , ex);
196+
Log.e(TAG , "Error reading file: " + uriContent , ex);
196197
return null;
197198
}
198199
}

app/src/main/java/org/qp/android/model/libQP/LibQpProxyImpl.java

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.anggrayudi.storage.file.MimeType;
2323

24+
import org.qp.android.QuestPlayerApplication;
2425
import org.qp.android.dto.libQP.ActionData;
2526
import org.qp.android.dto.libQP.ErrorData;
2627
import org.qp.android.dto.libQP.GetVarValuesResponse;
@@ -36,6 +37,7 @@
3637
import java.io.IOException;
3738
import java.util.ArrayList;
3839
import java.util.Locale;
40+
import java.util.Objects;
3941
import java.util.concurrent.ExecutorService;
4042
import java.util.concurrent.Executors;
4143
import java.util.concurrent.locks.ReentrantLock;
@@ -59,6 +61,14 @@ public class LibQpProxyImpl implements LibQpProxy, LibQpCallbacks {
5961
private final HtmlProcessor htmlProcessor;
6062
private final AudioPlayer audioPlayer;
6163

64+
private QuestPlayerApplication getApplication() {
65+
return (QuestPlayerApplication) context.getApplicationContext();
66+
}
67+
68+
private DocumentFile getCurGameDir() {
69+
return gameState.gameDir;
70+
}
71+
6272
public LibQpProxyImpl(
6373
Context context,
6474
GameContentResolver gameContentResolver,
@@ -288,7 +298,7 @@ private void doRunGame(final String id,
288298
gameState.gameTitle = title;
289299
gameState.gameDir = dir;
290300
gameState.gameFile = file;
291-
gameContentResolver.setGameDir(dir , context);
301+
getApplication().setCurrentGameDir(dir);
292302
if (!loadGameWorld()) return;
293303
gameStartTime = SystemClock.elapsedRealtime();
294304
lastMsCountCallTime = 0;
@@ -312,19 +322,20 @@ public void loadGameState(final Uri uri) {
312322
return;
313323
}
314324
final byte[] gameData;
315-
try (var in = context.getContentResolver().openInputStream(uri)) {
316-
try (var out = new ByteArrayOutputStream()) {
317-
if (in != null) {
318-
StreamUtil.copy(in, out);
319-
gameData = out.toByteArray();
320-
} else {
321-
throw new IOException("Input is NULL!");
322-
}
325+
var resolver = context.getContentResolver();
326+
try (var in = resolver.openInputStream(uri);
327+
var out = new ByteArrayOutputStream()) {
328+
if (in != null) {
329+
StreamUtil.copy(in, out);
330+
gameData = out.toByteArray();
331+
} else {
332+
throw new IOException("Input is NULL!");
323333
}
324334
} catch (IOException ex) {
325335
Log.e(TAG,"Failed to load game state", ex);
326336
return;
327337
}
338+
Log.d(TAG , String.valueOf(gameData.length));
328339
if (!nativeMethods.QSPOpenSavedGameFromData(gameData, gameData.length, true)) {
329340
showLastQspError();
330341
}
@@ -338,7 +349,8 @@ public void saveGameState(final Uri uri) {
338349
}
339350
byte[] gameData = nativeMethods.QSPSaveGameAsData(false);
340351
if (gameData == null) return;
341-
try (var out = context.getContentResolver().openOutputStream(uri, "w")) {
352+
var resolver = context.getContentResolver();
353+
try (var out = resolver.openOutputStream(uri, "w")) {
342354
if (out != null) {
343355
out.write(gameData);
344356
} else {
@@ -535,34 +547,35 @@ public void CloseFile(String path) {
535547
@Override
536548
public void OpenGame(String filename) {
537549
var inter = gameInterface;
538-
if (inter != null) {
539-
if (filename != null) {
540-
var saveFile = new File(filename);
541-
if (saveFile.exists()) {
542-
inter.doWithCounterDisabled(() -> loadGameState(Uri.fromFile(saveFile)));
543-
}
544-
} else {
545-
Log.e(TAG , "Save file not found");
546-
inter.showLoadGamePopup();
550+
if (inter == null) return;
551+
if (filename != null) {
552+
try {
553+
var uri = getApplication().fromFullPath(filename).getUri();
554+
inter.doWithCounterDisabled(() -> loadGameState(uri));
555+
} catch (Exception e) {
556+
Log.e(TAG , "Error: ", e);
547557
}
558+
} else {
559+
Log.e(TAG , "Save file not found");
560+
inter.showLoadGamePopup();
548561
}
549562
}
550563

551564
@Override
552565
public void SaveGame(String filename) {
553566
var inter = gameInterface;
554-
if (inter != null) {
555-
if (filename != null) {
556-
var file = new File(filename);
557-
var saveFile = createFindDFile(gameState.gameDir , MimeType.TEXT , file.getName());
558-
if (saveFile != null) {
559-
saveGameState(saveFile.getUri());
560-
} else {
561-
Log.e(TAG , "File not created");
562-
}
567+
if (inter == null) return;
568+
if (filename != null) {
569+
var file = new File(filename);
570+
var curGameDir = gameState.gameDir;
571+
var saveFile = createFindDFile(curGameDir , MimeType.TEXT , file.getName());
572+
if (saveFile != null) {
573+
saveGameState(saveFile.getUri());
563574
} else {
564-
inter.showSaveGamePopup();
575+
Log.e(TAG , "File not created");
565576
}
577+
} else {
578+
inter.showSaveGamePopup();
566579
}
567580
}
568581

@@ -626,19 +639,22 @@ public void ShowWindow(int type, boolean isShow) {
626639
// TODO: 09.10.2023 NEEED TO ADD ERROR CATCHER
627640
@Override
628641
public byte[] GetFileContents(String path) {
629-
return getFileContents(path);
642+
var name = gameState.gameDir.getName();
643+
if (name == null) return null;
644+
var targetFileUri = getApplication().fromFullPath(path).getUri();
645+
return getFileContents(context , targetFileUri);
630646
}
631647

632648
@Override
633649
public void ChangeQuestPath(String path) {
634-
var dir = DocumentFile.fromFile(new File(path));
635-
if (!dir.exists()) {
636-
Log.e(TAG,"InnerGameData directory not found: " + path);
650+
var newGameDir = getApplication().fromFullPath(path);
651+
if (!newGameDir.exists()) {
652+
Log.e(TAG,"Game directory not found: " + path);
637653
return;
638654
}
639-
if (!gameState.gameDir.equals(dir)) {
640-
gameState.gameDir = dir;
641-
gameContentResolver.setGameDir(dir , context);
655+
if (!Objects.equals(getCurGameDir() , newGameDir)) {
656+
gameState.gameDir = newGameDir;
657+
getApplication().setCurrentGameDir(newGameDir);
642658
}
643659
}
644660

app/src/main/java/org/qp/android/model/service/AudioPlayer.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
import android.os.Looper;
1010
import android.util.Log;
1111

12-
import com.anggrayudi.storage.file.DocumentFileCompat;
13-
import com.anggrayudi.storage.file.DocumentFileType;
14-
12+
import org.qp.android.QuestPlayerApplication;
1513
import org.qp.android.R;
1614
import org.qp.android.ui.dialogs.GameDialogType;
1715
import org.qp.android.ui.game.GameActivity;
@@ -32,6 +30,12 @@ public class AudioPlayer {
3230
private boolean isPaused = false;
3331
private Context context;
3432

33+
private String nameGameDir;
34+
35+
public void setNameGameDir(String nameGameDir) {
36+
this.nameGameDir = nameGameDir;
37+
}
38+
3539
public void start(Context context) {
3640
throwIfNotMainThread();
3741
this.context = context;
@@ -94,15 +98,20 @@ private void runOnAudioThread(final Runnable runnable) {
9498

9599
private void doPlay(final Sound sound) {
96100
var sysVolume = getSystemVolume(sound.volume);
101+
97102
if (sound.player != null) {
98103
sound.player.setVolume(sysVolume, sysVolume);
99104
if (!sound.player.isPlaying()) {
100105
sound.player.start();
101106
}
102107
return;
103108
}
104-
final var normPath = sound.path.replace("\\", "/");
105-
if (!DocumentFileCompat.doesExist(context , normPath)) {
109+
110+
var normPath = sound.path.replace("\\", "/");
111+
var application = (QuestPlayerApplication) context.getApplicationContext();
112+
var soundFile = application.fromFullPath(normPath);
113+
114+
if (soundFile == null) {
106115
var activity = (GameActivity) context;
107116
var controller = activity.getSettingsController();
108117
if (controller != null && controller.isUseMusicDebug) {
@@ -115,13 +124,10 @@ private void doPlay(final Sound sound) {
115124
}
116125
return;
117126
}
118-
var file = DocumentFileCompat.fromFullPath(
119-
context , normPath ,
120-
DocumentFileType.FILE , true
121-
);
127+
122128
var player = new MediaPlayer();
123129
try {
124-
player.setDataSource(context , file.getUri());
130+
player.setDataSource(context , soundFile.getUri());
125131
player.prepare();
126132
} catch (IOException ex) {
127133
Log.e(TAG,"Failed to initialize media player", ex);

0 commit comments

Comments
 (0)