Browse Source

Add support for love.filedropped in Android.

To send file to the filedropped callback, share the files to the game.
Note that for non-fused binary, if there's no game running, LOVE treat it as
*.love game to run.
Miku AuahDark 3 years ago
parent
commit
7b66e50cfc
3 changed files with 52 additions and 6 deletions
  1. 25 5
      src/common/android.cpp
  2. 7 0
      src/common/android.h
  3. 20 1
      src/modules/filesystem/NativeFile.cpp

+ 25 - 5
src/common/android.cpp

@@ -126,9 +126,6 @@ bool openURL(const std::string &url)
 
 	static jmethodID openURL = env->GetMethodID(clazz, "openURLFromLOVE", "(Ljava/lang/String;)Z");
 
-	if (openURL == nullptr)
-		return false;
-
 	jstring jstringURL = env->NewStringUTF(url.c_str());
 	jboolean result = env->CallBooleanMethod(clazz, openURL, jstringURL);
 
@@ -725,9 +722,9 @@ const char *getCRequirePath()
 	{
 		JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
 		jobject activity = (jobject) SDL_AndroidGetActivity();
+		jclass clazz = env->GetObjectClass(activity);
 
-		jclass clazz(env->GetObjectClass(activity));
-		jmethodID getCRequireMethod = env->GetMethodID(clazz, "getCRequirePath", "()Ljava/lang/String;");
+		static jmethodID getCRequireMethod = env->GetMethodID(clazz, "getCRequirePath", "()Ljava/lang/String;");
 
 		jstring cpath = (jstring) env->CallObjectMethod(activity, getCRequireMethod);
 		const char *utf = env->GetStringUTFChars(cpath, nullptr);
@@ -745,6 +742,29 @@ const char *getCRequirePath()
 	return path.c_str();
 }
 
+int getFDFromContentProtocol(const char *path)
+{
+	int fd = -1;
+
+	if (strstr(path, "content://") == path)
+	{
+		JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
+		jobject activity = (jobject) SDL_AndroidGetActivity();
+		jclass clazz = env->GetObjectClass(activity);
+
+		static jmethodID converter = env->GetMethodID(clazz, "convertToFileDescriptor", "(Ljava/lang/String;)I");
+
+		jstring uri = env->NewStringUTF(path);
+		fd = (int) env->CallIntMethod(activity, converter, uri);
+
+		env->DeleteLocalRef(uri);
+		env->DeleteLocalRef(clazz);
+		env->DeleteLocalRef(activity);
+	}
+
+	return fd;
+}
+
 int getFDFromLoveProtocol(const char *path)
 {
 	constexpr const char PROTOCOL[] = "love2d://fd/";

+ 7 - 0
src/common/android.h

@@ -96,6 +96,13 @@ bool checkFusedGame(void **physfsIO_Out);
 
 const char *getCRequirePath();
 
+/**
+ * Convert "content://" to file descriptor.
+ * @param path Path with content:// URI
+ * @return File descriptor if successful, -1 on failure.
+ */
+int getFDFromContentProtocol(const char *path);
+
 /**
  * Attempt to parse "(/)love2d://fd/<fd>" from path.
  * @param path Potentially special path.

+ 20 - 1
src/modules/filesystem/NativeFile.cpp

@@ -22,6 +22,10 @@
 #include "NativeFile.h"
 #include "common/utf8.h"
 
+#ifdef LOVE_ANDROID
+#include "common/android.h"
+#endif
+
 // Assume POSIX or Visual Studio.
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -84,7 +88,22 @@ bool NativeFile::open(Mode newmode)
 	if (file != nullptr)
 		return false;
 
-#ifdef LOVE_WINDOWS
+#if defined(LOVE_ANDROID)
+	// Try to handle content:// URI
+	int fd = love::android::getFDFromContentProtocol(filename.c_str());
+	if (fd != -1)
+	{
+		if (newmode != MODE_READ)
+		{
+			::close(fd);
+			throw love::Exception("%s is read-only.", filename.c_str());
+		}
+
+		file = fdopen(fd, "rb");
+	}
+	else
+		file = fopen(filename.c_str(), getModeString(newmode));
+#elif defined(LOVE_WINDOWS)
 	// make sure non-ASCII filenames work.
 	std::wstring modestr = to_widestr(getModeString(newmode));
 	std::wstring wfilename = to_widestr(filename);