Przeglądaj źródła

Merge branch 'setSource_mount_order'

Martin Felis 8 lat temu
rodzic
commit
ad5db40a9d

+ 17 - 45
love/src/jni/love/src/modules/filesystem/physfs/Filesystem.cpp

@@ -224,57 +224,29 @@ bool Filesystem::setSource(const char *source)
 	if (!love::android::createStorageDirectories())
 	if (!love::android::createStorageDirectories())
 		SDL_Log("Error creating storage directories!");
 		SDL_Log("Error creating storage directories!");
 
 
-	char* game_archive_ptr = NULL;
-	size_t game_archive_size = 0;
-	bool archive_loaded = false;
+	new_search_path = love::android::getSelectedGameFile();
 
 
-	// try to load the game that was sent to LÖVE via a Intent
-	archive_loaded = love::android::loadGameArchiveToMemory(love::android::getSelectedGameFile(), &game_archive_ptr, &game_archive_size);
-
-	if (!archive_loaded)
-	{
-		// try to load the game in the assets/ folder
-		archive_loaded = love::android::loadGameArchiveToMemory("game.love", &game_archive_ptr, &game_archive_size);
-	}
-
-	if (archive_loaded)
+	// try mounting first, if that fails, load to memory and mount
+	if (!PHYSFS_mount(new_search_path.c_str(), nullptr, 1))
 	{
 	{
-		if (!PHYSFS_mountMemory(game_archive_ptr, game_archive_size, love::android::freeGameArchiveMemory, "archive.zip", "/", 0))
+		// PHYSFS cannot yet mount a zip file inside an .apk
+		SDL_Log("Mounting %s did not work. Loading to memory.",
+				new_search_path.c_str());
+		char* game_archive_ptr = NULL;
+		size_t game_archive_size = 0;
+		if (!love::android::loadGameArchiveToMemory(
+					new_search_path.c_str(), &game_archive_ptr,
+					&game_archive_size))
 		{
 		{
-			SDL_Log("Mounting of in-memory game archive failed!");
-			love::android::freeGameArchiveMemory(game_archive_ptr);
+			SDL_Log("Failure memory loading archive %s", new_search_path.c_str());
 			return false;
 			return false;
 		}
 		}
-	}
-	else
-	{
-		// try to load the game in the directory that was sent to LÖVE via an
-		// Intent ...
-		std::string game_path = std::string(love::android::getSelectedGameFile());
-
-		if (game_path == "")
-		{
-			// ... or fall back to the game at /sdcard/lovegame
-			game_path = "/sdcard/lovegame/";
-		}
-
-		SDL_RWops *sdcard_main = SDL_RWFromFile(std::string(game_path + "main.lua").c_str(), "rb");
-
-		if (sdcard_main)
+		if (!PHYSFS_mountMemory(
+			    game_archive_ptr, game_archive_size,
+			    love::android::freeGameArchiveMemory, "archive.zip", "/", 0))
 		{
 		{
-			new_search_path = game_path;
-			sdcard_main->close(sdcard_main);
-
-			if (!PHYSFS_mount(new_search_path.c_str(), nullptr, 1))
-			{
-				SDL_Log("mounting of %s failed", new_search_path.c_str());
-				return false;
-			}
-		}
-		else
-		{
-			// Neither assets/game.love or /sdcard/lovegame was mounted
-			// sucessfully, therefore simply fail.
+			SDL_Log("Failure mounting in-memory archive.");
+			love::android::freeGameArchiveMemory(game_archive_ptr);
 			return false;
 			return false;
 		}
 		}
 	}
 	}

+ 98 - 47
love/src/main/java/org/love2d/android/GameActivity.java

@@ -2,9 +2,11 @@ package org.love2d.android;
 
 
 import org.libsdl.app.SDLActivity;
 import org.libsdl.app.SDLActivity;
 
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.List;
 import java.io.BufferedInputStream;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.BufferedOutputStream;
+import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStream;
@@ -13,6 +15,7 @@ import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URL;
 
 
 import android.app.Activity;
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.app.DownloadManager;
 import android.app.DownloadManager;
 import android.app.ProgressDialog;
 import android.app.ProgressDialog;
 import android.content.Context;
 import android.content.Context;
@@ -39,7 +42,7 @@ public class GameActivity extends SDLActivity {
     private static Context context;
     private static Context context;
     private static Vibrator vibrator = null;
     private static Vibrator vibrator = null;
     private static boolean immersiveActive = false;
     private static boolean immersiveActive = false;
-
+    private static boolean mustCacheArchive = false;
 		@Override 
 		@Override 
 		protected String[] getLibraries() {
 		protected String[] getLibraries() {
 			return new String[] {
 			return new String[] {
@@ -75,14 +78,18 @@ public class GameActivity extends SDLActivity {
       handleIntent (intent);
       handleIntent (intent);
       resetNative();
       resetNative();
       startNative();
       startNative();
-    };
+    }
 
 
     protected void handleIntent (Intent intent) {
     protected void handleIntent (Intent intent) {
       Uri game = intent.getData();
       Uri game = intent.getData();
+
       if (game != null) {
       if (game != null) {
+        // If we have a game via the intent data we we try to figure out how we have to load it. We
+        // support the following variations:
+        // * a main.lua file: set gamePath to the directory containing main.lua
+        // * otherwise: set gamePath to the file
         if (game.getScheme().equals ("file")) {
         if (game.getScheme().equals ("file")) {
           Log.d("GameActivity", "Received intent with path: " + game.getPath());
           Log.d("GameActivity", "Received intent with path: " + game.getPath());
-
           // If we were given the path of a main.lua then use its
           // If we were given the path of a main.lua then use its
           // directory. Otherwise use full path.
           // directory. Otherwise use full path.
           List<String> path_segments = game.getPathSegments();
           List<String> path_segments = game.getPathSegments();
@@ -92,12 +99,52 @@ public class GameActivity extends SDLActivity {
             gamePath = game.getPath();
             gamePath = game.getPath();
           }
           }
         } else {
         } else {
-          copyGameToCache (game);
+            Log.e("GameActivity", "Unsupported scheme: '" + game.getScheme() + "'.");
+
+            AlertDialog.Builder alert_dialog  = new AlertDialog.Builder(this);
+            alert_dialog.setMessage("Could not load LÖVE game '" + game.getPath()
+                    + "' as it uses unsupported scheme '" + game.getScheme()
+                    + "'. Please contact the developer.");
+            alert_dialog.setTitle("LÖVE for Android Error");
+            alert_dialog.setPositiveButton("Exit",
+                    new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog,int id) {
+                            finish();
+                        }
+                    });
+            alert_dialog.setCancelable(false);
+            alert_dialog.create().show();
         }
         }
+      } else {
+          // No game specified via the intent data -> check whether we have a game.love in our assets.
+          boolean game_love_in_assets = false;
+          try {
+              List<String> assets = Arrays.asList(getAssets().list(""));
+              game_love_in_assets = assets.contains("game.love");
+          } catch (Exception e) {
+              Log.d("GameActivity", "could not list application assets:" + e.getMessage());
+          }
 
 
-        Log.d("GameActivity", "new gamePath: " + gamePath);
+          if (game_love_in_assets) {
+              // If we have a game.love in our assets folder copy it to the cache folder
+              // so that we can load it from native LÖVE code
+              String destination_file = this.getCacheDir().getPath()+"/game.love";
+              if (mustCacheArchive && copyAssetFile("game.love", destination_file))
+                  gamePath = destination_file;
+              else
+                  gamePath = "game.love";
+          } else {
+              // If no game.love was found fall back to the game in <external storage>/lovegame
+              File ext = Environment.getExternalStorageDirectory();              
+              if ((new File(ext,"/lovegame/main.lua")).exists()) {
+                  gamePath = ext.getPath() + "/lovegame/";
+              }
+          }
       }
       }
-    };
+
+      Log.d("GameActivity", "new gamePath: " + gamePath);
+    }
 
 
     @Override
     @Override
     protected void onDestroy() {
     protected void onDestroy() {
@@ -197,56 +244,60 @@ public class GameActivity extends SDLActivity {
       i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       context.startActivity(i);
       context.startActivity(i);
     }
     }
-  
-    void copyGameToCache (Uri sourceuri)
+
+    /**
+     * Copies a given file from the assets folder to the destination.
+     * @return true if successful
+     */
+    boolean copyAssetFile(String fileName, String destinationFileName)
     {
     {
-      String destinationFilename = this.getCacheDir().getPath()+"/downloaded.love";
-      gamePath = destinationFilename;
-
-      BufferedOutputStream bos = null;
-      try {
-        bos = new BufferedOutputStream(new FileOutputStream(destinationFilename, false));
-      } catch (IOException e) {
-        Log.d ("GameActivity", "Could not open destination file:" + e.getMessage());
-      }
+        boolean success = false;
 
 
-      int chunk_read = 0;
-      int bytes_written = 0;
+        // open source and destination streams
+        InputStream source_stream = null;
+        try {
+            source_stream = getAssets().open(fileName);
+        } catch (IOException e) {
+            Log.d("GameActivity", "Could not open game.love from assets: " + e.getMessage());
+        }
 
 
-      BufferedInputStream bis = null;
-      if (sourceuri.getScheme().equals("content")) {
+        BufferedOutputStream destination_stream = null;
         try {
         try {
-          bis = new BufferedInputStream(getContentResolver().openInputStream(sourceuri));
+            destination_stream = new BufferedOutputStream(new FileOutputStream(destinationFileName, false));
         } catch (IOException e) {
         } catch (IOException e) {
-          Log.d ("GameActivity", "Could not open game file:" + e.getMessage());
+            Log.d ("GameActivity", "Could not open destination file: " + e.getMessage());
         }
         }
-      } else {
-        Log.d ("GameActivity", "Unsupported scheme: " + sourceuri.getScheme());
-      }
 
 
-      if (bis != null) {
-        // actual copying
+        // perform the copying
+        int chunk_read = 0;
+        int bytes_written = 0;
+
+        assert (source_stream != null && destination_stream != null);
+
         try {
         try {
-          byte[] buf = new byte[1024];
-          chunk_read = bis.read(buf);
-          do {
-            bos.write(buf, 0, chunk_read);
-            bytes_written += chunk_read;
-            chunk_read = bis.read(buf);        
-          } while(chunk_read != -1);
+            byte[] buf = new byte[1024];
+            chunk_read = source_stream.read(buf);
+            do {
+                destination_stream.write(buf, 0, chunk_read);
+                bytes_written += chunk_read;
+                chunk_read = source_stream.read(buf);
+            } while (chunk_read != -1);
         } catch (IOException e) {
         } catch (IOException e) {
-          Log.d ("GameActivity", "Copying failed:" + e.getMessage());
-        } 
-      }
+            Log.d("GameActivity", "Copying failed:" + e.getMessage());
+        }
 
 
-      // close streams
-      try {
-        if (bis != null) bis.close();
-        if (bos != null) bos.close();
-      } catch (IOException e) {
-        Log.d ("GameActivity", "Copying failed: " + e.getMessage());
-      }
+        // close streams
+        try {
+            if (source_stream != null) source_stream.close();
+            if (destination_stream != null) destination_stream.close();
+            success = true;
+        } catch (IOException e) {
+            Log.d ("GameActivity", "Copying failed: " + e.getMessage());
+        }
 
 
-      Log.d("GameActivity", "Copied " + bytes_written + " bytes");
+        Log.d("GameActivity", "Successfully copied " + fileName
+                + " to " + destinationFileName
+                + " (" + bytes_written + " bytes written).");
+        return success;
     }
     }
-}
+}