Added share buttons to android

This commit is contained in:
Yousef Khadadeh 2026-05-31 18:35:57 +03:00
parent e2a62e852c
commit 7f94f65bea
16 changed files with 146 additions and 19 deletions

View file

@ -96,4 +96,5 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.core:core:1.18.0"
}

View file

@ -22,6 +22,8 @@
void updateTextboxAndCursorPos(java.lang.String, int, int);
void startNetworkService();
void stopNetworkService();
void shareText(java.lang.String);
void shareInternalFile(java.lang.String, java.lang.String);
}
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLActivity {

View file

@ -89,6 +89,16 @@
android:value="When connected to a server/hosting a server, keep the connection alive even when the application is in the background."/>
</service>
<provider
android:name="com.erroratline0.infinipaint.InfiniPaintFileProvider"
android:authorities="com.erroratline0.infinipaint.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<activity android:name="com.erroratline0.infinipaint.InfiniPaint"
android:label="@string/app_name"
android:windowSoftInputMode="adjustNothing"

View file

@ -18,8 +18,11 @@
package com.erroratline0.infinipaint;
import static androidx.core.content.FileProvider.getUriForFile;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@ -35,6 +38,8 @@ import org.libsdl.app.SDLActivity;
import org.libsdl.app.SDLDummyEdit;
import org.libsdl.app.SDLSurface;
import java.io.File;
public class InfiniPaint extends SDLActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -148,4 +153,33 @@ public class InfiniPaint extends SDLActivity {
static public void stopNetworkService() {
mSingleton.stopService(new Intent(mSingleton, InfiniPaintNetworkService.class));
}
static public void shareInternalFile(String filePath, String mimeType) {
File newFile = new File(getContext().getFilesDir(), filePath);
Uri contentUri;
try {
contentUri = getUriForFile(getContext(), "com.erroratline0.infinipaint.fileprovider", newFile);
}
catch (Exception e) {
Log.v("INFO", "[shareInternalFile] Exception " + e);
return;
}
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
sendIntent.setType(mimeType);
Intent shareIntent = Intent.createChooser(sendIntent, null);
getContext().startActivity(shareIntent);
}
static public void shareText(String textToSend) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textToSend);
sendIntent.setType("text/plain");
Intent shareIntent = Intent.createChooser(sendIntent, null);
getContext().startActivity(shareIntent);
}
}

View file

@ -0,0 +1,9 @@
package com.erroratline0.infinipaint;
import androidx.core.content.FileProvider;
public class InfiniPaintFileProvider extends FileProvider {
public InfiniPaintFileProvider() {
super(R.xml.file_paths);
}
}

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="infinipaint_saves" path="saves/" />
</paths>

View file

@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.7.3'
classpath 'com.android.tools.build:gradle:8.13.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View file

@ -10,6 +10,7 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit

View file

@ -1,6 +1,6 @@
#Thu Nov 11 18:20:34 PST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M13.1202 17.0228L8.92129 14.7324C8.19135 15.5125 7.15261 16 6 16C3.79086 16 2 14.2091 2 12C2 9.79086 3.79086 8 6 8C7.15255 8 8.19125 8.48746 8.92118 9.26746L13.1202 6.97713C13.0417 6.66441 13 6.33707 13 6C13 3.79086 14.7909 2 17 2C19.2091 2 21 3.79086 21 6C21 8.20914 19.2091 10 17 10C15.8474 10 14.8087 9.51251 14.0787 8.73246L9.87977 11.0228C9.9583 11.3355 10 11.6629 10 12C10 12.3371 9.95831 12.6644 9.87981 12.9771L14.0788 15.2675C14.8087 14.4875 15.8474 14 17 14C19.2091 14 21 15.7909 21 18C21 20.2091 19.2091 22 17 22C14.7909 22 13 20.2091 13 18C13 17.6629 13.0417 17.3355 13.1202 17.0228ZM6 14C7.10457 14 8 13.1046 8 12C8 10.8954 7.10457 10 6 10C4.89543 10 4 10.8954 4 12C4 13.1046 4.89543 14 6 14ZM17 8C18.1046 8 19 7.10457 19 6C19 4.89543 18.1046 4 17 4C15.8954 4 15 4.89543 15 6C15 7.10457 15.8954 8 17 8ZM17 20C18.1046 20 19 19.1046 19 18C19 16.8954 18.1046 16 17 16C15.8954 16 15 16.8954 15 18C15 19.1046 15.8954 20 17 20Z"></path></svg>

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -58,6 +58,28 @@ namespace AndroidJNICalls {
bool textChanged = false;
bool cursorChanged = false;
void shareInternalFile(const std::string& filePath, const std::string& mimeType) {
Logger::get().log(Logger::LogType::INFO, "[AndroidJNICalls::shareInternalFile] Share internal file " + filePath);
JNIEnv* env = static_cast<JNIEnv*>(SDL_GetAndroidJNIEnv());
jobject activity = (jobject)SDL_GetAndroidActivity();
jclass clazz = env->GetObjectClass(activity);
jmethodID method_id = env->GetStaticMethodID(clazz, "shareInternalFile", "(Ljava/lang/String;Ljava/lang/String;)V");
env->CallStaticVoidMethod(clazz, method_id, string2jstring(env, filePath), string2jstring(env, mimeType));
env->DeleteLocalRef(activity);
env->DeleteLocalRef(clazz);
}
void shareText(const std::string& str) {
Logger::get().log(Logger::LogType::INFO, "[AndroidJNICalls::shareText] Share text " + str);
JNIEnv* env = static_cast<JNIEnv*>(SDL_GetAndroidJNIEnv());
jobject activity = (jobject)SDL_GetAndroidActivity();
jclass clazz = env->GetObjectClass(activity);
jmethodID method_id = env->GetStaticMethodID(clazz, "shareText", "(Ljava/lang/String;)V");
env->CallStaticVoidMethod(clazz, method_id, string2jstring(env, str));
env->DeleteLocalRef(activity);
env->DeleteLocalRef(clazz);
}
int get_android_text_pos_from_cursor_pos(const std::shared_ptr<RichText::TextBox>& t, const RichText::TextPosition& p) {
return t->get_utf16_location_from_codepoint_location(t->get_codepoint_location_from_text_position(p));
}

View file

@ -26,6 +26,8 @@ struct InputManager;
namespace AndroidJNICalls {
extern InputManager* globalInputManager;
void shareInternalFile(const std::string& filePath, const std::string& mimeType);
void shareText(const std::string& str);
void startTextInput(CustomEvents::InputTextBoxID newTextboxID, const std::shared_ptr<RichText::TextBox>& newTextbox, const std::shared_ptr<RichText::TextBox::Cursor>& newCursor, const std::shared_ptr<RichText::TextStyleModifier::ModifierMap>& modMap, int inputType);
void startNetworkService();
void stopNetworkService();

View file

@ -29,10 +29,6 @@
#include "../../GUIStuff/ElementHelpers/CheckBoxHelpers.hpp"
#include <include/pathops/SkPathOps.h>
#define MINIMUM_DISTANCE_FROM_FIRST_POINT 3.0f
#define MINIMUM_DISTANCE_TO_NEXT_POINT 0.002f
#define DRAW_MINIMUM_LIMIT 1.0f
BrushTool::BrushTool(DrawingProgram& initDrawP):
DrawingProgramToolBase(initDrawP)
{}

View file

@ -427,6 +427,17 @@ void FileSelectScreen::move_selected_files(const std::filesystem::path& fromPath
}
}
void FileSelectScreen::share_selected_files() {
for(const FileInfo& f : fileList) {
if(f.selected) {
#ifdef __ANDROID__
AndroidJNICalls::shareInternalFile("saves/" + f.fileName + ".infpnt", "application/octet-stream");
#endif
break;
}
}
}
void FileSelectScreen::duplicate_selected_files(const std::filesystem::path& inPath) {
std::vector<std::string> toFolderListNames;
try {
@ -571,6 +582,15 @@ void FileSelectScreen::edit_action_bar() {
update_file_list(fileList, savePath, false);
editMode = false;
});
#ifdef __ANDROID__
if(numberOfSelectedEntries == 1) {
edit_action_bar_button("share", "data/icons/RemixIcon/share-line.svg", "Share", [&] {
share_selected_files();
update_file_list(fileList, savePath, false);
editMode = false;
});
}
#endif
}
else if(selectedMenu == SelectedMenu::TRASH) {
edit_action_bar_button("restore", "data/icons/RemixIcon/refresh-line.svg", "Restore", [&] {

View file

@ -112,6 +112,7 @@ class FileSelectScreen : public Screen {
};
void move_selected_files(const std::filesystem::path& fromPath, const std::filesystem::path& toPath, TrashMoveType trashMoveType);
void duplicate_selected_files(const std::filesystem::path& inPath);
void share_selected_files();
void delete_selected_files_in_trash();
enum class MoreOptionsMenu {

View file

@ -255,13 +255,25 @@ void PhoneDrawingProgramScreen::top_toolbar_settings_popup() {
input_text_field(gui, "lobby", "Lobby", &serverToConnectTo, {
.immutable = true
});
text_button(gui, "Host button", "Copy & Host", {
.wide = true,
.onClick = [&] {
main.input.set_clipboard_str(serverToConnectTo);
main.world->start_hosting(serverToConnectTo, serverLocalID);
topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
}
left_to_right_line_layout(gui, [&] {
text_button(gui, "Host button", "Copy & Host", {
.wide = true,
.onClick = [&] {
main.input.set_clipboard_str(serverToConnectTo);
main.world->start_hosting(serverToConnectTo, serverLocalID);
topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
}
});
#ifdef __ANDROID__
text_button(gui, "Share and host button", "Share & Host", {
.wide = true,
.onClick = [&] {
AndroidJNICalls::shareText(serverToConnectTo);
main.world->start_hosting(serverToConnectTo, serverLocalID);
topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
}
});
#endif
});
}
});
@ -291,12 +303,23 @@ void PhoneDrawingProgramScreen::top_toolbar_settings_popup() {
input_text_field(gui, "lobby", "Lobby", &serverToConnectTo, {
.immutable = true
});
text_button(gui, "Copy button", "Copy", {
.wide = true,
.onClick = [&] {
main.input.set_clipboard_str(serverToConnectTo);
topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
}
left_to_right_line_layout(gui, [&] {
text_button(gui, "Copy button", "Copy", {
.wide = true,
.onClick = [&] {
main.input.set_clipboard_str(serverToConnectTo);
topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
}
});
#ifdef __ANDROID__
text_button(gui, "Share button", "Share", {
.wide = true,
.onClick = [&] {
AndroidJNICalls::shareText(serverToConnectTo);
topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
}
});
#endif
});
}
});