Browse Source

Android: Add support for sharing debug.txt (#12370)

rubenwardy 1 year ago
parent
commit
4baf56520d

+ 12 - 1
android/app/src/main/AndroidManifest.xml

@@ -59,6 +59,17 @@
 			android:name=".UnzipService"
 			android:enabled="true"
 			android:exported="false" />
-	</application>
+
+		<provider
+			android:name="androidx.core.content.FileProvider"
+			android:authorities="net.minetest.minetest.fileprovider"
+			android:grantUriPermissions="true"
+			android:exported="false">
+			<meta-data
+				android:name="android.support.FILE_PROVIDER_PATHS"
+				android:resource="@xml/filepaths" />
+		</provider>
+
+</application>
 
 </manifest>

+ 21 - 0
android/app/src/main/java/net/minetest/minetest/GameActivity.java

@@ -26,6 +26,7 @@ import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.text.InputType;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.WindowManager;
@@ -36,7 +37,9 @@ import android.widget.LinearLayout;
 
 import androidx.annotation.Keep;
 import androidx.appcompat.app.AlertDialog;
+import androidx.core.content.FileProvider;
 
+import java.io.File;
 import java.util.Objects;
 
 // Native code finds these methods by name (see porting_android.cpp).
@@ -183,4 +186,22 @@ public class GameActivity extends NativeActivity {
 	public String getCachePath() {
 		return Utils.getCacheDirectory(this).getAbsolutePath();
 	}
+
+	public void shareFile(String path) {
+		File file = new File(path);
+		if (!file.exists()) {
+			Log.e("GameActivity", "File " + file.getAbsolutePath() + " doesn't exist");
+			return;
+		}
+
+		Uri fileUri = FileProvider.getUriForFile(this, "net.minetest.minetest.fileprovider", file);
+
+		Intent intent = new Intent(Intent.ACTION_SEND, fileUri);
+		intent.setDataAndType(fileUri, getContentResolver().getType(fileUri));
+		intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+		intent.putExtra(Intent.EXTRA_STREAM, fileUri);
+
+		Intent shareIntent = Intent.createChooser(intent, null);
+		startActivity(shareIntent);
+	}
 }

+ 3 - 0
android/app/src/main/res/xml/filepaths.xml

@@ -0,0 +1,3 @@
+<paths>
+	<external-files-path path="Minetest/" name="minetest" />
+</paths>

+ 8 - 1
builtin/mainmenu/tab_about.lua

@@ -128,7 +128,9 @@ return {
 			fgettext("Active renderer:") .. "\n" ..
 			core.formspec_escape(core.get_screen_info().render_info) .. "]"
 
-		if PLATFORM ~= "Android" then
+		if PLATFORM == "Android" then
+			fs = fs .. "button[0,4;3.5,1;share_debug;" .. fgettext("Share debug log") .. "]"
+		else
 			fs = fs .. "tooltip[userdata;" ..
 					fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" ..
 							"and texture packs in a file manager / explorer.") .. "]"
@@ -142,6 +144,11 @@ return {
 			core.open_url("https://www.minetest.net")
 		end
 
+		if fields.share_debug then
+			local path = core.get_user_path() .. DIR_DELIM .. "debug.txt"
+			core.share_file(path)
+		end
+
 		if fields.userdata then
 			core.open_dir(core.get_user_path())
 		end

+ 2 - 0
doc/menu_lua_api.txt

@@ -46,6 +46,8 @@ core.open_url(url)
 core.open_dir(path)
 ^ opens the path in the system file browser/explorer, returns false on failure.
 ^ Must be an existing directory.
+core.share_file(path)
+^ Android only. Shares file using the share popup
 core.get_version() (possible in async calls)
 ^ returns current core version
 

+ 12 - 0
src/porting_android.cpp

@@ -213,6 +213,18 @@ void openURIAndroid(const std::string &url)
 	jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl);
 }
 
+void shareFileAndroid(const std::string &path)
+{
+	jmethodID url_open = jnienv->GetMethodID(nativeActivity, "shareFile",
+			"(Ljava/lang/String;)V");
+
+	FATAL_ERROR_IF(url_open == nullptr,
+			"porting::shareFileAndroid unable to find java openURI method");
+
+	jstring jurl = jnienv->NewStringUTF(path.c_str());
+	jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl);
+}
+
 int getInputDialogState()
 {
 	jmethodID dialogstate = jnienv->GetMethodID(nativeActivity,

+ 7 - 0
src/porting_android.h

@@ -60,6 +60,13 @@ void showInputDialog(const std::string &acceptButton,
 
 void openURIAndroid(const std::string &url);
 
+/**
+ * Opens a share intent to the file at path
+ *
+ * @param path
+ */
+void shareFileAndroid(const std::string &path);
+
 /**
  * WORKAROUND for not working callbacks from java -> c++
  * get current state of input dialog

+ 14 - 0
src/script/lua_api/l_mainmenu.cpp

@@ -876,6 +876,19 @@ int ModApiMainMenu::l_open_dir(lua_State *L)
 	return 1;
 }
 
+/******************************************************************************/
+int ModApiMainMenu::l_share_file(lua_State *L)
+{
+#ifdef __ANDROID__
+	std::string path = luaL_checkstring(L, 1);
+	porting::shareFileAndroid(path);
+	lua_pushboolean(L, true);
+#else
+	lua_pushboolean(L, false);
+#endif
+	return 1;
+}
+
 /******************************************************************************/
 int ModApiMainMenu::l_do_async_callback(lua_State *L)
 {
@@ -941,6 +954,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
 	API_FCT(get_max_supp_proto);
 	API_FCT(open_url);
 	API_FCT(open_dir);
+	API_FCT(share_file);
 	API_FCT(do_async_callback);
 }
 

+ 2 - 0
src/script/lua_api/l_mainmenu.h

@@ -152,6 +152,8 @@ private:
 
 	static int l_open_dir(lua_State *L);
 
+	static int l_share_file(lua_State *L);
+
 
 	// async
 	static int l_do_async_callback(lua_State *L);