added support for opening level set zip files in Android version
authorHolger Schemel <info@artsoft.org>
Fri, 24 May 2024 14:35:49 +0000 (16:35 +0200)
committerHolger Schemel <info@artsoft.org>
Fri, 24 May 2024 14:35:49 +0000 (16:35 +0200)
build-projects/android/app/src/main/AndroidManifest.xml.tmpl
build-projects/android/app/src/main/java/org/artsoft/rocksndiamonds/rocksndiamonds.java
src/events.c
src/libgame/zip/ioapi.c

index 8331804d0c5a7ddd0730fed9e61a7c2f44832cf4..9a90444fc4247db3d8bd793a5a4d5717ab885f78 100644 (file)
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:mimeType="application/zip" />
+            </intent-filter>
         </activity>
     </application>
 
index eeec2ea4a4bfe833e180bc2f8c4525200370c632..ee7aed022906797b6d2b2a04a4107a5dfe8724fd 100644 (file)
@@ -3,4 +3,118 @@ package org.artsoft.rocksndiamonds;
 
 import org.libsdl.app.SDLActivity;
 
-public class rocksndiamonds extends SDLActivity { }
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.provider.OpenableColumns;
+import android.util.Log;
+
+public class rocksndiamonds extends SDLActivity {
+    private static final String TAG = "RND";
+    private String[] args;
+
+    @Override
+    protected String[] getArguments() {
+        return args;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        Log.d(TAG, "onCreate");
+
+        // init program arguments
+        args = new String[0];
+
+        // prevent SDL from sending "drop file" event on app start; use program arguments instead
+        Intent intent = getIntent();
+        handleIntent(intent, true);
+        intent.setData(null);
+
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        Log.d(TAG, "onNewIntent");
+
+        // handle file opened with "open with" when app is already running
+        handleIntent(intent, false);
+    }
+
+    private void handleIntent(Intent intent, boolean onCreate) {
+        Log.d(TAG, "handleIntent");
+
+        Uri uri = intent.getData();
+        if (uri == null) {
+            Log.d(TAG, "handleIntent: uri == null");
+            return;
+        }
+
+        if (onCreate) {
+            Log.d(TAG, "handleIntent: starting app with file as argument");
+
+            // app not running yet -- starting app with "--drop-file" argument
+            setProgramArgs(uri);
+        } else {
+            Log.d(TAG, "handleIntent: sending drop event to running app");
+
+            // app already running -- sending file as a "drop file" event
+            sendUriAsDroppedFile(uri);
+        }
+    }
+
+    public void sendUriAsDroppedFile(Uri uri) {
+        SDLActivity.onNativeDropFile(getFileDescriptorStringFromUri(uri));
+    }
+
+    private int getFileDescriptorFromUri(Uri uri) {
+        int fd = -1;
+
+        try {
+            ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "r");
+            if (pfd == null) {
+                throw new RuntimeException("pfd is null");
+            }
+
+            fd = pfd.dup().detachFd();
+            pfd.close();
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to convert URI " + uri.toString() + " to file descriptor", e);
+        }
+
+        return fd;
+    }
+
+    private String getFileDescriptorStringFromUri(Uri uri) {
+        return "fd:" + getFileDescriptorFromUri(uri);
+    }
+
+    private void setProgramArgs(Uri uri) {
+        Log.d(TAG, "setProgramArgs");
+
+        // log some file details
+        Cursor returnCursor = getContentResolver().query(uri, null, null, null, null);
+        int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+        int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
+        returnCursor.moveToFirst();
+        Log.e(TAG, "setProgramArgs: file name: " + returnCursor.getString(nameIndex));
+        Log.e(TAG, "setProgramArgs: file size: " + Long.toString(returnCursor.getLong(sizeIndex)));
+
+        String scheme = uri.getScheme();
+        if (scheme != null) {
+            if (scheme.equals("content")) {
+                // convert URI to file descriptor
+                String fd = getFileDescriptorStringFromUri(uri);
+                Log.e(TAG, "setProgramArgs: setting argument to file descriptor: " + fd);
+                args = new String[]{ "--drop-file", fd };
+            } else if (scheme.equals("file")) {
+                // directly use regular file
+                String path = uri.getPath();
+                Log.e(TAG, "setProgramArgs: setting argument to file path: " + path);
+                args = new String[]{ "--drop-file", path };
+            }
+        }
+    }
+}
index 04f69108527feaca46f5eca02ce2fc30b82f3ad9..3406adc52f108ccde75355aaa67d1903be8f6d98 100644 (file)
@@ -1505,7 +1505,8 @@ static int HandleDropFileEvent(char *filename)
   Debug("event:dropfile", "filename == '%s'", filename);
 
   // check and extract dropped zip files into correct user data directory
-  if (!strSuffixLower(filename, ".zip"))
+  if (!strSuffixLower(filename, ".zip") &&
+      !strPrefixLower(filename, "fd:"))
   {
     Warn("file '%s' not supported", filename);
 
@@ -1615,6 +1616,12 @@ static void HandleDropCompleteEvent(int num_level_sets_succeeded,
 
 void HandleDropEvent(Event *event)
 {
+  Debug("event:drop", (event->type == SDL_DROPBEGIN    ? "SDL_DROPBEGIN" :
+                      event->type == SDL_DROPFILE      ? "SDL_DROPFILE" :
+                      event->type == SDL_DROPTEXT      ? "SDL_DROPTEXT" :
+                      event->type == SDL_DROPCOMPLETE  ? "SDL_DROPCOMPLETE" :
+                      "(unknown drop event type)"));
+
   static boolean confirm_on_drop_complete = FALSE;
   static int num_level_sets_succeeded = 0;
   static int num_artwork_sets_succeeded = 0;
index 0aa6347ac4106620b6c3d3aa851dd5b7f08e57ec..20da15240ad5ab441702cf64ed5626724239ce1d 100644 (file)
@@ -121,7 +121,11 @@ static voidpf ZCALLBACK fopen64_file_func(ZIP_UNUSED voidpf opaque, const void *
 
     if ((filename != NULL) && (mode_fopen != NULL))
     {
-        file = fopen64((const char*)filename, mode_fopen);
+        const char *fd_prefix = "fd:";
+        if (strncmp(filename, fd_prefix, strlen(fd_prefix)) == 0)
+            file = fdopen(dup(atoi(&filename[strlen(fd_prefix)])), mode_fopen);
+        else
+            file = fopen64((const char*)filename, mode_fopen);
         return file_build_ioposix(file, (const char*)filename);
     }
     return file;