APDE icon indicating copy to clipboard operation
APDE copied to clipboard

Complied App can't access any of its files

Open robotdognz opened this issue 4 years ago • 4 comments

I've been working on a game for a few months and have just started looking into testing it on other phones. When running in App mode or exporting a signed .apk, I can't access any of the files in the application directory using commands like "dataPath("")" and "context.getFilesDir()", the application doesn't see them and says the directory is empty. I've found that I can get around this by using AssetManager.list("subfolder"), but this doesn't work in preview mode, it returns an empty list. I'm not sure if I'm missing something, but it seems like some file functionality works in one mode and some in the other.

Using functions like "loadImage("filename.type")" works fine in both modes, but my game needs to parse all the image files in a couple of sub-directories and create objects for each of them, which can't be done with specific calls to loadImage().

I've done a lot of googling trying to find a solution. Am I doing something wrong, or is this a bug?

robotdognz avatar Jan 05 '21 04:01 robotdognz

I've written some code that allows the parsing and then loading of images in subfolders that works for both App and Preview:

	// generate all the relative file paths
	File[] tileFiles;
	try {
		// App mode

		AssetManager am = context.getAssets();
		String tilePath = "tiles";
		String[] tileStrings = am.list(tilePath);

		if (tileStrings.length == 0) {
			throw new IOException();
		}

		tileFiles = new File[tileStrings.length];
		PApplet.println("Tile strings: " + tileStrings.length);

		// make relative files from all of the tile strings
		for (int i = 0; i < tileStrings.length; i++) {
			tileFiles[i] = new File(tilePath + '/' + tileStrings[i]);
		}
		PApplet.println("All tile files created using AsesetManager");

	} catch (IOException e) {
		// Preview mode

		String base = p.sketchPath("");
		File tilePath = new File(base + "/tiles" + '/');

		File[] absoluteFiles = tilePath.listFiles();
		tileFiles = new File[absoluteFiles.length];
		PApplet.println("Tile paths: " + absoluteFiles.length);

		for (int i = 0; i < absoluteFiles.length; i++) {
			String relativeFile = absoluteFiles[i].toString();
			relativeFile = relativeFile.replace(base + '/', "");
			tileFiles[i] = new File(relativeFile);
		}
		PApplet.println("All tile files created using absolute file paths");
	}

	// load all the images
	try {
		// App mode

		for (int i = 0; i < tileFiles.length; i++) {
			PImage temp = p.loadImage(tileFiles[i].toString());
			PApplet.println("" + temp + " - " + tileFiles[i]);
		}
		PApplet.println("All tile images loaded using relative file paths");

	} catch (IllegalArgumentException e) {
		// Preview mode

		String base = p.sketchPath("");
		for (int i = 0; i < tileFiles.length; i++) {
			String fullPath = base + '/' + tileFiles[i].toString();
			PImage temp = p.loadImage(fullPath);
			PApplet.println("" + temp + " - " + tileFiles[i]);
		}
		PApplet.println("All tile images loaded using absolute file paths");
	}

robotdognz avatar Jan 06 '21 00:01 robotdognz

Looks great! Until which target Api have you tested?

EmmanuelPil avatar Jan 06 '21 03:01 EmmanuelPil

Edit: I've updated the code and replaced Path with String, it works on all the phones I have access to now. I've tried it on phones with API's from 23-29.

If you combine my file path generating code with the solution found here https://github.com/Calsign/APDE/issues/88, then you only need the app mode code for loading the images

robotdognz avatar Jan 06 '21 03:01 robotdognz

In preview mode, the data folder gets copied into the app's internal storage. In app mode, the data folder lives in assets inside the APK. I talk about this in the technical quirks section of the preview mode wiki page.

I don't fully remember the specifics enough to understand the nuanced behavior you're seeing here, but it definitely sounds like it's worth it for me to revisit the way the data folder is handled. For reference the relevant code is in Build.java and PreviewUtil.java .

Calsign avatar Nov 12 '21 07:11 Calsign