mirror of
https://github.com/OMGeeky/andors-trail.git
synced 2026-02-23 15:38:29 +01:00
Android 11 has new requirements regarding file access.
This prototype has working test code for Android 11 but there is still a lot missing like exlaination dialogues, refactoring, etc
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
>
|
||||
<uses-sdk
|
||||
android:minSdkVersion="4"
|
||||
android:targetSdkVersion="28"
|
||||
android:targetSdkVersion="30"
|
||||
/>
|
||||
|
||||
<supports-screens
|
||||
@@ -31,6 +31,8 @@
|
||||
android:description="@string/app_description"
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/AndorsTrailTheme_Blue"
|
||||
android:hasFragileUserData="true"
|
||||
android:preserveLegacyExternalStorage="true"
|
||||
>
|
||||
<activity
|
||||
android:name=".activity.StartScreenActivity"
|
||||
@@ -61,6 +63,16 @@
|
||||
<activity android:name=".activity.BulkSelectionInterface" android:theme="@style/AndorsTrailDialogTheme_Blue" />
|
||||
<activity android:name=".activity.SkillInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
|
||||
<activity android:name=".activity.DisplayWorldMapActivity" />
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="com.gpl.rpg.AndorsTrail.fileprovider"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/fileprovider" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
Binary file not shown.
7
AndorsTrail/res/xml/fileprovider.xml
Normal file
7
AndorsTrail/res/xml/fileprovider.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<external-path path="." name="external" />
|
||||
<external-files-path path="." name="external_files" />
|
||||
<files-path path="." name="files" />
|
||||
<root-path path="." name="root" />
|
||||
</paths>
|
||||
@@ -7,6 +7,7 @@ import java.util.Locale;
|
||||
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.Constants;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
|
||||
import com.gpl.rpg.AndorsTrail.util.Pair;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -118,9 +119,7 @@ public final class AndorsTrailApplication extends Application {
|
||||
super.onCreate();
|
||||
|
||||
if ( DEVELOPMENT_DEBUGMESSAGES && isExternalStorageWritable() ) {
|
||||
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
File appDirectory = new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
File appDirectory = Savegames.getExternalDirectory(getApplicationContext(), Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
File logDirectory = new File( appDirectory, "log" );
|
||||
File logFile = new File( logDirectory, "logcat" + System.currentTimeMillis() + ".txt" );
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.gpl.rpg.AndorsTrail.model.item.Inventory;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.Loot;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
|
||||
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
|
||||
import com.gpl.rpg.AndorsTrail.view.ItemContainerAdapter;
|
||||
@@ -332,7 +333,17 @@ public final class Dialogs {
|
||||
|
||||
String text = currentActivity.getResources().getString(R.string.dialog_newversion_message);
|
||||
|
||||
if (!hasPermissions(currentActivity)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
if (hasPermissions(currentActivity)) {
|
||||
// TODO: Unterscheiden, ob Quell- und/oder
|
||||
if (Savegames.getUsedSavegameSlots(currentActivity).size() == 0) {
|
||||
text += "";
|
||||
} else {
|
||||
text += "";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!hasPermissions(currentActivity)) {
|
||||
text += currentActivity.getResources().getString(R.string.dialog_newversion_permission_information);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gpl.rpg.AndorsTrail.activity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
@@ -15,7 +16,9 @@ import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
@@ -85,7 +88,7 @@ public final class DisplayWorldMapActivity extends AndorsTrailBaseActivity {
|
||||
Coord offsetWorldmapTo;
|
||||
@SuppressLint("NewApi")
|
||||
private void update() {
|
||||
File worldmap = WorldMapController.getCombinedWorldMapFile(worldMapSegmentName);
|
||||
File worldmap = WorldMapController.getCombinedWorldMapFile(this, worldMapSegmentName);
|
||||
|
||||
if (!worldmap.exists()) {
|
||||
Toast.makeText(this, getResources().getString(R.string.menu_button_worldmap_failed), Toast.LENGTH_LONG).show();
|
||||
@@ -104,14 +107,15 @@ public final class DisplayWorldMapActivity extends AndorsTrailBaseActivity {
|
||||
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
|
||||
if (predefinedMap == null) continue;
|
||||
if (!predefinedMap.visited) continue;
|
||||
if (!WorldMapController.fileForMapExists(predefinedMap)) continue;
|
||||
if (!WorldMapController.fileForMapExists(this, predefinedMap)) continue;
|
||||
|
||||
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
|
||||
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
|
||||
}
|
||||
|
||||
|
||||
String url = "file://" + worldmap.getAbsolutePath() + '?'
|
||||
// String url = "content://com.gpl.rpg.AndorsTrail.fileprovider/worldmap" + worldmap.getAbsolutePath() + '?'
|
||||
// FileProvider.getUri
|
||||
Uri uri = FileProvider.getUriForFile(this, "com.gpl.rpg.AndorsTrail.fileprovider", worldmap);
|
||||
String url = uri.toString() + '?'
|
||||
+ (world.model.player.position.x + map.worldPosition.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
|
||||
+ ','
|
||||
+ (world.model.player.position.y + map.worldPosition.y-1) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE;
|
||||
|
||||
@@ -70,9 +70,9 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
|
||||
ViewGroup newSlotContainer = (ViewGroup) findViewById(R.id.loadsave_save_to_new_slot_container);
|
||||
Button createNewSlot = (Button) findViewById(R.id.loadsave_save_to_new_slot);
|
||||
|
||||
addSavegameSlotButtons(slotList, params, Savegames.getUsedSavegameSlots());
|
||||
addSavegameSlotButtons(slotList, params, Savegames.getUsedSavegameSlots(this));
|
||||
|
||||
checkAndRequestPermissions();
|
||||
// checkAndRequestPermissions();
|
||||
|
||||
if (!isLoading) {
|
||||
createNewSlot.setTag(SLOT_NUMBER_CREATE_NEW_SLOT);
|
||||
@@ -137,7 +137,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
|
||||
|
||||
public void loadsave(int slot) {
|
||||
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT) {
|
||||
List<Integer> usedSlots = Savegames.getUsedSavegameSlots();
|
||||
List<Integer> usedSlots = Savegames.getUsedSavegameSlots(this);
|
||||
if (usedSlots.isEmpty()) slot = SLOT_NUMBER_FIRST_SLOT;
|
||||
else slot = Collections.max(usedSlots) + 1;
|
||||
}
|
||||
@@ -152,7 +152,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
|
||||
private String getConfirmOverwriteQuestion(int slot) {
|
||||
if (isLoading) return null;
|
||||
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT) return null; // if we're creating a new slot
|
||||
if (!Savegames.getSlotFile(slot).exists()) return null;
|
||||
if (!Savegames.getSlotFile(slot, this).exists()) return null;
|
||||
|
||||
if (preferences.displayOverwriteSavegame == AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_ALWAYS) {
|
||||
return getString(R.string.loadsave_save_overwrite_confirmation_all);
|
||||
@@ -192,7 +192,7 @@ public final class LoadSaveActivity extends AndorsTrailBaseActivity implements O
|
||||
|
||||
|
||||
if (isLoading) {
|
||||
if(!Savegames.getSlotFile(slot).exists()) {
|
||||
if(!Savegames.getSlotFile(slot, this).exists()) {
|
||||
showErrorLoadingEmptySlot();
|
||||
} else {
|
||||
final FileHeader header = Savegames.quickload(this, slot);
|
||||
|
||||
@@ -190,7 +190,7 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
});
|
||||
}
|
||||
|
||||
boolean hasSavegames = !Savegames.getUsedSavegameSlots().isEmpty();
|
||||
boolean hasSavegames = !Savegames.getUsedSavegameSlots(getActivity()).isEmpty();
|
||||
startscreen_load.setEnabled(hasSavegames);
|
||||
}
|
||||
|
||||
@@ -199,13 +199,29 @@ public class StartScreenActivity_MainMenu extends Fragment {
|
||||
|
||||
@TargetApi(23)
|
||||
public static void checkAndRequestPermissions(final Activity activity) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
activity.requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, READ_EXTERNAL_STORAGE_REQUEST);
|
||||
}
|
||||
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
activity.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
|
||||
String info = "";
|
||||
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
|
||||
&& activity.getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
||||
info = "RW permission on external folder exists";
|
||||
if (Savegames.getUsedSavegameSlots(activity.getApplicationContext()).size() == 0) {
|
||||
info += ". Destination folder is empty, migrating data.";
|
||||
Savegames.MigrateData(activity.getApplicationContext());
|
||||
} else {
|
||||
info += ". Destination folder is not empty, no migration.";
|
||||
}
|
||||
} else {
|
||||
info = "No rw permission on external folder";
|
||||
}
|
||||
final Dialog d = CustomDialogFactory.createDialog(activity,
|
||||
"Info",
|
||||
activity.getResources().getDrawable(android.R.drawable.ic_delete),
|
||||
info,
|
||||
null,
|
||||
true);
|
||||
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
|
||||
CustomDialogFactory.show(d);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.gpl.rpg.AndorsTrail.context;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
@@ -58,4 +59,5 @@ public final class ControllerContext {
|
||||
public Resources getResources() {
|
||||
return app.get().getResources();
|
||||
}
|
||||
public Context getContext() {return app.get().getApplicationContext(); }
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ public final class MapController {
|
||||
world.maps.worldMapRequiresUpdate = true;
|
||||
|
||||
if (!updateWorldmap) return;
|
||||
WorldMapController.updateWorldMap(world, res);
|
||||
WorldMapController.updateWorldMap(controllers.getContext(), world, res);
|
||||
mapLayoutListeners.onMapTilesChanged(world.model.currentMaps.map, world.model.currentMaps.tileMap);
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ public final class MovementController implements TimedMessageTask.Callback {
|
||||
moveBlockedActors(newMap, model.currentMaps.tileMap);
|
||||
refreshMonsterAggressiveness(newMap, model.player);
|
||||
controllers.effectController.updateSplatters(newMap);
|
||||
WorldMapController.updateWorldMap(world, res);
|
||||
WorldMapController.updateWorldMap(controllers.getContext(), world, res);
|
||||
}
|
||||
|
||||
private boolean mayMovePlayer() {
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.NamedWorldMapArea;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
|
||||
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
@@ -40,12 +41,12 @@ public final class WorldMapController {
|
||||
private static final int WORLDMAP_SCREENSHOT_TILESIZE = 8;
|
||||
public static final int WORLDMAP_DISPLAY_TILESIZE = WORLDMAP_SCREENSHOT_TILESIZE;
|
||||
|
||||
public static void updateWorldMap(final WorldContext world, final Resources res) {
|
||||
updateWorldMap(world, world.model.currentMaps.map, world.model.currentMaps.tileMap, world.model.currentMaps.tiles, res);
|
||||
public static void updateWorldMap(Context context, final WorldContext world, final Resources res) {
|
||||
updateWorldMap(context, world, world.model.currentMaps.map, world.model.currentMaps.tileMap, world.model.currentMaps.tiles, res);
|
||||
}
|
||||
|
||||
private static void updateWorldMap(
|
||||
final WorldContext world,
|
||||
Context context, final WorldContext world,
|
||||
final PredefinedMap map,
|
||||
final LayeredTileMap mapTiles,
|
||||
final TileCollection cachedTiles,
|
||||
@@ -53,15 +54,15 @@ public final class WorldMapController {
|
||||
final String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(map.name);
|
||||
if (worldMapSegmentName == null) return;
|
||||
|
||||
if (!shouldUpdateWorldMap(map, worldMapSegmentName, world.maps.worldMapRequiresUpdate)) return;
|
||||
if (!shouldUpdateWorldMap(context, map, worldMapSegmentName, world.maps.worldMapRequiresUpdate)) return;
|
||||
|
||||
(new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... arg0) {
|
||||
final MapRenderer renderer = new MapRenderer(world, map, mapTiles, cachedTiles);
|
||||
try {
|
||||
updateCachedBitmap(map, renderer);
|
||||
updateWorldMapSegment(res, world, worldMapSegmentName);
|
||||
updateCachedBitmap(context, map, renderer);
|
||||
updateWorldMapSegment(context, res, world, worldMapSegmentName);
|
||||
world.maps.worldMapRequiresUpdate = false;
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
|
||||
L.log("WorldMapController: Updated worldmap segment " + worldMapSegmentName + " for map " + map.name);
|
||||
@@ -74,22 +75,22 @@ public final class WorldMapController {
|
||||
}).execute();
|
||||
}
|
||||
|
||||
private static boolean shouldUpdateWorldMap(PredefinedMap map, String worldMapSegmentName, boolean forceUpdate) {
|
||||
private static boolean shouldUpdateWorldMap(Context context, PredefinedMap map, String worldMapSegmentName, boolean forceUpdate) {
|
||||
if (forceUpdate) return true;
|
||||
if (!map.visited) return true;
|
||||
File file = getFileForMap(map, false);
|
||||
File file = getFileForMap(context, map, false);
|
||||
if (!file.exists()) return true;
|
||||
|
||||
file = getCombinedWorldMapFile(worldMapSegmentName);
|
||||
file = getCombinedWorldMapFile(context, worldMapSegmentName);
|
||||
if (!file.exists()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void updateCachedBitmap(PredefinedMap map, MapRenderer renderer) throws IOException {
|
||||
ensureWorldmapDirectoryExists();
|
||||
private static void updateCachedBitmap(Context context, PredefinedMap map, MapRenderer renderer) throws IOException {
|
||||
ensureWorldmapDirectoryExists(context);
|
||||
|
||||
File file = getFileForMap(map, false);
|
||||
File file = getFileForMap(context, map, false);
|
||||
if (file.exists()) return;
|
||||
|
||||
Bitmap image = renderer.drawMap();
|
||||
@@ -150,9 +151,8 @@ public final class WorldMapController {
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureWorldmapDirectoryExists() throws IOException {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
File dir = new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
private static void ensureWorldmapDirectoryExists(Context context) throws IOException {
|
||||
File dir = Savegames.getExternalDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
dir = new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
@@ -160,33 +160,32 @@ public final class WorldMapController {
|
||||
File noMediaFile = new File(dir, ".nomedia");
|
||||
if (!noMediaFile.exists()) noMediaFile.createNewFile();
|
||||
}
|
||||
public static boolean fileForMapExists(PredefinedMap map) {
|
||||
public static boolean fileForMapExists(Context context, PredefinedMap map) {
|
||||
if (map.lastSeenLayoutHash.length() > 0) {
|
||||
return getPngFile(map.name + '.' + map.lastSeenLayoutHash).exists();
|
||||
return getPngFile(context, map.name + '.' + map.lastSeenLayoutHash).exists();
|
||||
}
|
||||
return getPngFile(map.name).exists();
|
||||
return getPngFile(context, map.name).exists();
|
||||
}
|
||||
private static File getFileForMap(PredefinedMap map, boolean verifyFileExists) {
|
||||
private static File getFileForMap(Context context, PredefinedMap map, boolean verifyFileExists) {
|
||||
if (map.lastSeenLayoutHash.length() > 0) {
|
||||
File fileWithHash = getPngFile(map.name + '.' + map.lastSeenLayoutHash);
|
||||
File fileWithHash = getPngFile(context, map.name + '.' + map.lastSeenLayoutHash);
|
||||
if (!verifyFileExists) return fileWithHash;
|
||||
else if (fileWithHash.exists()) return fileWithHash;
|
||||
}
|
||||
return getPngFile(map.name);
|
||||
return getPngFile(context, map.name);
|
||||
}
|
||||
private static File getPngFile(String fileName) {
|
||||
return new File(getWorldmapDirectory(), fileName + ".png");
|
||||
private static File getPngFile(Context context, String fileName) {
|
||||
return new File(getWorldmapDirectory(context), fileName + ".png");
|
||||
}
|
||||
private static File getWorldmapDirectory() {
|
||||
File dir = Environment.getExternalStorageDirectory();
|
||||
dir = new File(dir, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
private static File getWorldmapDirectory(Context context) {
|
||||
File dir = Savegames.getExternalDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
return new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
|
||||
}
|
||||
public static File getCombinedWorldMapFile(String segmentName) {
|
||||
return new File(getWorldmapDirectory(), Constants.FILENAME_WORLDMAP_HTMLFILE_PREFIX + segmentName + Constants.FILENAME_WORLDMAP_HTMLFILE_SUFFIX);
|
||||
public static File getCombinedWorldMapFile(Context context, String segmentName) {
|
||||
return new File(getWorldmapDirectory(context), Constants.FILENAME_WORLDMAP_HTMLFILE_PREFIX + segmentName + Constants.FILENAME_WORLDMAP_HTMLFILE_SUFFIX);
|
||||
}
|
||||
|
||||
private static String getWorldMapSegmentAsHtml(Resources res, WorldContext world, String segmentName) {
|
||||
private static String getWorldMapSegmentAsHtml(Context context, Resources res, WorldContext world, String segmentName) {
|
||||
WorldMapSegment segment = world.maps.worldMapSegments.get(segmentName);
|
||||
|
||||
Map<String, File> displayedMapFilenamesPerMapName = new HashMap<String, File>(segment.maps.size());
|
||||
@@ -195,7 +194,7 @@ public final class WorldMapController {
|
||||
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
|
||||
if (predefinedMap == null) continue;
|
||||
if (!predefinedMap.visited) continue;
|
||||
File f = WorldMapController.getFileForMap(predefinedMap, true);
|
||||
File f = WorldMapController.getFileForMap(context, predefinedMap, true);
|
||||
if (!f.exists()) continue;
|
||||
displayedMapFilenamesPerMapName.put(map.mapName, f);
|
||||
|
||||
@@ -294,9 +293,9 @@ public final class WorldMapController {
|
||||
return new CoordRect(topLeft, new Size(bottomRight.x - topLeft.x, bottomRight.y - topLeft.y));
|
||||
}
|
||||
|
||||
public static void updateWorldMapSegment(Resources res, WorldContext world, String segmentName) throws IOException {
|
||||
String mapAsHtml = getWorldMapSegmentAsHtml(res, world, segmentName);
|
||||
File outputFile = getCombinedWorldMapFile(segmentName);
|
||||
public static void updateWorldMapSegment(Context context, Resources res, WorldContext world, String segmentName) throws IOException {
|
||||
String mapAsHtml = getWorldMapSegmentAsHtml(context, res, world, segmentName);
|
||||
File outputFile = getCombinedWorldMapFile(context, segmentName);
|
||||
PrintWriter pw = new PrintWriter(outputFile);
|
||||
pw.write(mapAsHtml);
|
||||
pw.close();
|
||||
|
||||
@@ -47,7 +47,7 @@ public class LegacySavegamesContentAdaptations {
|
||||
if (segmentsCovered.contains(segment.name)) continue;
|
||||
segmentsCovered.add(segment.name);
|
||||
try {
|
||||
WorldMapController.updateWorldMapSegment(res, world, segment.name);
|
||||
WorldMapController.updateWorldMapSegment(controllers.getContext(), res, world, segment.name);
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
|
||||
L.log("Forcing generation of worldmap file for segment " + segment.name);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.SystemClock;
|
||||
|
||||
@@ -39,6 +41,59 @@ public final class Savegames {
|
||||
|
||||
private static long lastBackup = 0;
|
||||
|
||||
public static void MigrateData(Context context) {
|
||||
try {
|
||||
copy(new File(Environment.getExternalStorageDirectory(), Constants.CHEAT_DETECTION_FOLDER),
|
||||
getExternalDirectory(context, Constants.CHEAT_DETECTION_FOLDER));
|
||||
copy(new File(Environment.getExternalStorageDirectory(), Constants.FILENAME_SAVEGAME_DIRECTORY),
|
||||
getExternalDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY));
|
||||
} catch (IOException e) {
|
||||
L.log("Error migrating data: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void copy(File sourceLocation, File targetLocation) throws IOException {
|
||||
if (!sourceLocation.exists()) {
|
||||
return;
|
||||
}
|
||||
if (sourceLocation.isDirectory()) {
|
||||
copyDirectory(sourceLocation, targetLocation);
|
||||
} else {
|
||||
copyFile(sourceLocation, targetLocation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyDirectory(File source, File target) throws IOException {
|
||||
if (!target.exists()) {
|
||||
target.mkdir();
|
||||
}
|
||||
|
||||
for (String f : source.list()) {
|
||||
copy(new File(source, f), new File(target, f));
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyFile(File source, File target) throws IOException {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
in = new FileInputStream(source);
|
||||
out = new FileOutputStream(target);
|
||||
byte[] buf = new byte[1024];
|
||||
int length;
|
||||
while ((length = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, length);
|
||||
}
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static enum LoadSavegameResult {
|
||||
success
|
||||
, unknownError
|
||||
@@ -71,7 +126,7 @@ public final class Savegames {
|
||||
androidContext.deleteFile(Constants.FILENAME_SAVEGAME_QUICKSAVE);
|
||||
writeCheatCheck(androidContext, savedVersion, id);
|
||||
} else if (SystemClock.uptimeMillis() > lastBackup + 120000) {
|
||||
writeBackup(savegame, id);
|
||||
writeBackup(androidContext, savegame, id);
|
||||
lastBackup = SystemClock.uptimeMillis();
|
||||
}
|
||||
}
|
||||
@@ -83,9 +138,8 @@ public final class Savegames {
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeBackup(byte[] savegame, String playerId) throws IOException {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
File cheatDetectionFolder = new File(root, Constants.CHEAT_DETECTION_FOLDER);
|
||||
private static void writeBackup(Context androidContext, byte[] savegame, String playerId) throws IOException {
|
||||
File cheatDetectionFolder = getExternalDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
|
||||
if (!cheatDetectionFolder.exists()) cheatDetectionFolder.mkdir();
|
||||
File backupFile = new File(cheatDetectionFolder, playerId + "X");
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(backupFile);
|
||||
@@ -111,7 +165,7 @@ public final class Savegames {
|
||||
if (!saveWorld(world, androidContext, SLOT_QUICKSAVE)) {
|
||||
return LoadSavegameResult.unknownError;
|
||||
}
|
||||
getSlotFile(slot).delete();
|
||||
getSlotFile(slot, androidContext).delete();
|
||||
writeCheatCheck(androidContext, DENY_LOADING_BECAUSE_GAME_IS_CURRENTLY_PLAYED, fh.playerId);
|
||||
}
|
||||
return result;
|
||||
@@ -129,8 +183,7 @@ public final class Savegames {
|
||||
|
||||
private static boolean triedToCheat(Context androidContext, FileHeader fh) throws IOException {
|
||||
long savedVersionToCheck = 0;
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
File cheatDetectionFolder = new File(root, Constants.CHEAT_DETECTION_FOLDER);
|
||||
File cheatDetectionFolder = getExternalDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
|
||||
if (!cheatDetectionFolder.exists()) cheatDetectionFolder.mkdir();
|
||||
File cheatDetectionFile = new File(cheatDetectionFolder, fh.playerId);
|
||||
if (cheatDetectionFile.exists()) {
|
||||
@@ -172,31 +225,35 @@ public final class Savegames {
|
||||
if (slot == SLOT_QUICKSAVE) {
|
||||
return androidContext.openFileOutput(Constants.FILENAME_SAVEGAME_QUICKSAVE, Context.MODE_PRIVATE);
|
||||
} else {
|
||||
ensureSavegameDirectoryExists();
|
||||
return new FileOutputStream(getSlotFile(slot));
|
||||
ensureSavegameDirectoryExists(androidContext);
|
||||
return new FileOutputStream(getSlotFile(slot, androidContext));
|
||||
}
|
||||
}
|
||||
private static void ensureSavegameDirectoryExists() {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
File dir = new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
private static void ensureSavegameDirectoryExists(Context context) {
|
||||
File dir = getExternalDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
}
|
||||
private static FileInputStream getInputFile(Context androidContext, int slot) throws IOException {
|
||||
if (slot == SLOT_QUICKSAVE) {
|
||||
return androidContext.openFileInput(Constants.FILENAME_SAVEGAME_QUICKSAVE);
|
||||
} else {
|
||||
return new FileInputStream(getSlotFile(slot));
|
||||
return new FileInputStream(getSlotFile(slot, androidContext));
|
||||
}
|
||||
}
|
||||
|
||||
public static File getSlotFile(int slot) {
|
||||
File root = getSavegameDirectory();
|
||||
public static File getSlotFile(int slot, Context context) {
|
||||
File root = getExternalDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
return new File(root, Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + slot);
|
||||
}
|
||||
|
||||
private static File getSavegameDirectory() {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
return new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
public static File getExternalDirectory(Context context, String name) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
|
||||
return context.getExternalFilesDir(name);
|
||||
}
|
||||
else {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
return new File(root, name);
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveWorld(WorldContext world, OutputStream outStream, String displayInfo) throws IOException {
|
||||
@@ -240,7 +297,7 @@ public final class Savegames {
|
||||
public static FileHeader quickload(Context androidContext, int slot) {
|
||||
try {
|
||||
if (slot != SLOT_QUICKSAVE) {
|
||||
File f = getSlotFile(slot);
|
||||
File f = getSlotFile(slot, androidContext);
|
||||
if (!f.exists()) return null;
|
||||
}
|
||||
FileInputStream fos = getInputFile(androidContext, slot);
|
||||
@@ -255,8 +312,7 @@ public final class Savegames {
|
||||
}
|
||||
|
||||
private static void writeCheatCheck(Context androidContext, long savedVersion, String playerId) throws IOException {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
File cheatDetectionFolder = new File(root, Constants.CHEAT_DETECTION_FOLDER);
|
||||
File cheatDetectionFolder = getExternalDirectory(androidContext, Constants.CHEAT_DETECTION_FOLDER);
|
||||
if (!cheatDetectionFolder.exists()) cheatDetectionFolder.mkdir();
|
||||
File cheatDetectionFile = new File(cheatDetectionFolder, playerId);
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(cheatDetectionFile);
|
||||
@@ -273,10 +329,11 @@ public final class Savegames {
|
||||
}
|
||||
|
||||
private static final Pattern savegameFilenamePattern = Pattern.compile(Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + "(\\d+)");
|
||||
public static List<Integer> getUsedSavegameSlots() {
|
||||
|
||||
public static List<Integer> getUsedSavegameSlots(Context context) {
|
||||
try {
|
||||
final List<Integer> result = new ArrayList<Integer>();
|
||||
getSavegameDirectory().listFiles(new FilenameFilter() {
|
||||
getExternalDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY).listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File f, String filename) {
|
||||
Matcher m = savegameFilenamePattern.matcher(filename);
|
||||
|
||||
Reference in New Issue
Block a user