diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 6fc69ab4..e92b2a44 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -19,11 +19,22 @@
android:supportsRtl="true"
android:theme="@style/Theme.Main">
+
+
+
+
+
diff --git a/android/app/src/main/java/mw/gri/android/FileProvider.java b/android/app/src/main/java/mw/gri/android/FileProvider.java
new file mode 100644
index 00000000..c7bd8b08
--- /dev/null
+++ b/android/app/src/main/java/mw/gri/android/FileProvider.java
@@ -0,0 +1,7 @@
+package mw.gri.android;
+
+public class FileProvider extends androidx.core.content.FileProvider {
+ public FileProvider() {
+ super(R.xml.paths);
+ }
+}
diff --git a/android/app/src/main/java/mw/gri/android/MainActivity.java b/android/app/src/main/java/mw/gri/android/MainActivity.java
index 7d6d3848..f57d3e29 100644
--- a/android/app/src/main/java/mw/gri/android/MainActivity.java
+++ b/android/app/src/main/java/mw/gri/android/MainActivity.java
@@ -4,6 +4,7 @@ import android.Manifest;
import android.content.*;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
@@ -17,6 +18,7 @@ import androidx.annotation.NonNull;
import androidx.camera.core.*;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.content.ContextCompat;
+import androidx.core.content.FileProvider;
import androidx.core.graphics.Insets;
import androidx.core.view.DisplayCutoutCompat;
import androidx.core.view.ViewCompat;
@@ -24,6 +26,7 @@ import androidx.core.view.WindowInsetsCompat;
import com.google.androidgamesdk.GameActivity;
import com.google.common.util.concurrent.ListenableFuture;
+import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -62,6 +65,11 @@ public class MainActivity extends GameActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
+ // Clear cache on start.
+ if (savedInstanceState == null) {
+ Utils.deleteDirectoryContent(new File(getExternalCacheDir().getPath()), false);
+ }
+
// Setup environment variables for native code.
try {
Os.setenv("HOME", getExternalFilesDir("").getPath(), true);
@@ -70,6 +78,7 @@ public class MainActivity extends GameActivity {
} catch (ErrnoException e) {
throw new RuntimeException(e);
}
+
super.onCreate(null);
// Register receiver to finish activity from the BackgroundService.
@@ -334,4 +343,14 @@ public class MainActivity extends GameActivity {
// Pass image from camera into native code.
public native void onCameraImage(byte[] buff, int rotation);
+
+ // Called from native code to share image from provided path.
+ public void shareImage(String path) {
+ File file = new File(path);
+ Uri uri = FileProvider.getUriForFile(this, "mw.gri.android.fileprovider", file);
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ intent.setType("image/*");
+ startActivity(Intent.createChooser(intent, "Share image"));
+ }
}
\ No newline at end of file
diff --git a/android/app/src/main/java/mw/gri/android/Utils.java b/android/app/src/main/java/mw/gri/android/Utils.java
index 3723c7d6..47d1d566 100644
--- a/android/app/src/main/java/mw/gri/android/Utils.java
+++ b/android/app/src/main/java/mw/gri/android/Utils.java
@@ -8,6 +8,7 @@ import android.media.Image;
import androidx.camera.core.ImageProxy;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.nio.ByteBuffer;
public class Utils {
@@ -135,4 +136,14 @@ public class Utils {
rowStart += plane.getRowStride();
}
}
+
+ public static boolean deleteDirectoryContent(File directoryToBeDeleted, boolean deleteDirectory) {
+ File[] allContents = directoryToBeDeleted.listFiles();
+ if (allContents != null) {
+ for (File file : allContents) {
+ deleteDirectoryContent(file, true);
+ }
+ }
+ return directoryToBeDeleted.delete();
+ }
}
diff --git a/android/app/src/main/res/xml/paths.xml b/android/app/src/main/res/xml/paths.xml
new file mode 100644
index 00000000..db427353
--- /dev/null
+++ b/android/app/src/main/res/xml/paths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/gui/platform/android/mod.rs b/src/gui/platform/android/mod.rs
index 0159302b..c2d25c19 100644
--- a/src/gui/platform/android/mod.rs
+++ b/src/gui/platform/android/mod.rs
@@ -12,6 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+use std::env;
+use std::ffi::OsString;
+use std::fs::File;
+use std::io::Write;
+use std::path::PathBuf;
use lazy_static::lazy_static;
use std::sync::Arc;
use parking_lot::RwLock;
@@ -116,6 +121,22 @@ impl PlatformCallbacks for Android {
}
fn share_data(&self, name: String, data: Vec) -> Result<(), std::io::Error> {
+ // Create file at cache dir.
+ let default_cache = OsString::from(dirs::cache_dir().unwrap());
+ let mut cache = PathBuf::from(env::var_os("XDG_CACHE_HOME").unwrap_or(default_cache));
+ cache.push("images");
+ std::fs::create_dir_all(cache.to_str().unwrap())?;
+ cache.push(name);
+ let mut image = File::create_new(cache.clone()).unwrap();
+ image.write_all(data.as_slice()).unwrap();
+ image.sync_all().unwrap();
+ // Call share modal at system.
+ let vm = unsafe { jni::JavaVM::from_raw(self.android_app.vm_as_ptr() as _) }.unwrap();
+ let env = vm.attach_current_thread().unwrap();
+ let arg_value = env.new_string(cache.to_str().unwrap()).unwrap();
+ self.call_java_method("shareImage",
+ "(Ljava/lang/String;)V",
+ &[JValue::Object(&JObject::from(arg_value))]).unwrap();
Ok(())
}
}
diff --git a/src/gui/views/qr.rs b/src/gui/views/qr.rs
index cbd443b8..08d2e695 100644
--- a/src/gui/views/qr.rs
+++ b/src/gui/views/qr.rs
@@ -19,7 +19,7 @@ use std::thread;
use egui::{SizeHint, TextureHandle, TextureOptions};
use egui::load::SizedTexture;
use egui_extras::image::load_svg_bytes_with_size;
-use image::{EncodableLayout, ExtendedColorType, ImageEncoder};
+use image::{ExtendedColorType, ImageEncoder};
use image::codecs::png::{CompressionType, FilterType, PngEncoder};
use qrcodegen::QrCode;
use crate::gui::Colors;