Commit 561c0cc

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2023-10-13 10:34:17
add native method for sharing data directly
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent c8bca6e
Changed files (3)
android
app
src
main
kotlin
com
derdilla
blood_pressure_app
lib
model
platform_integration
android/app/src/main/kotlin/com/derdilla/blood_pressure_app/StorageProvider.kt
@@ -20,12 +20,16 @@ class StorageProvider(private var context: Context,
          when (call.method) {
              "shareFile" -> shareFile(call.argument<String>("path")!!,
                  call.argument<String>("mimeType")!!, call.argument<String>("name"))
+             "shareData" -> shareData(call.argument<ByteArray>("data")!!,
+                 call.argument<String>("mimeType")!!, call.argument<String>("name")!!)
         }
     }
 
     /**
      * Show the share sheet for saving a file.
      *
+     * @param path The path to the file in internal storage
+     * @param mimeType The mime type that gets send with the intend
      * @param name Used to make the name of the shared file different from the original name.
      */
     private fun shareFile(path: String, mimeType: String, name: String?) {
@@ -41,12 +45,43 @@ class StorageProvider(private var context: Context,
         startActivity(context, shareIntent, null)
     }
 
+    /**
+     * Create a file from data and show start Intent to show a share sheet.
+     *
+     * @param data The data that gets shared
+     * @param mimeType The mime type that gets send with the intend
+     * @param name The name of the shared file
+     */
+    private fun shareData(data: ByteArray, mimeType: String, name: String) {
+        val uri = sharableUriFromData(data, name)
+
+        val sendIntent: Intent = Intent().apply {
+            action = Intent.ACTION_SEND
+            putExtra(Intent.EXTRA_STREAM, uri)
+            type = mimeType
+        }
+
+        val shareIntent = Intent.createChooser(sendIntent, null)
+        startActivity(context, shareIntent, null)
+    }
+
 
     private fun sharableUriFromPath(path: String, name: String?): Uri {
         val initialFile = File(path)
+        if (!initialFile.exists()) throw IllegalArgumentException("Tried to create URI from nonexistent file")
+
         val sharablePath = File(shareFolder, name ?: initialFile.name)
         if (sharablePath.exists()) sharablePath.delete()
         initialFile.copyTo(sharablePath)
         return getUriForFile(context, "com.derdilla.bloodPressureApp.share", sharablePath)
     }
+
+    private fun sharableUriFromData(data: ByteArray, name: String): Uri {
+        if (!shareFolder.exists()) shareFolder.mkdirs()
+        val sharablePath = File(shareFolder, name)
+        if (sharablePath.exists()) sharablePath.delete()
+        sharablePath.createNewFile()
+        sharablePath.writeBytes(data)
+        return getUriForFile(context, "com.derdilla.bloodPressureApp.share", sharablePath)
+    }
 }
\ No newline at end of file
lib/model/export_import.dart
@@ -282,18 +282,17 @@ class Exporter {
     final filename = 'blood_press_${DateTime.now().toIso8601String()}';
     final ext = exportSettings.exportFormat.name;
 
-    final file = File(join(Directory.systemTemp.path, '$filename.$ext'));
-    file.writeAsBytesSync(fileContents);
-
     assert(Platform.isAndroid || Platform.isIOS);
     if (exportSettings.defaultExportDir.isNotEmpty) {
+      final file = File(join(Directory.systemTemp.path, '$filename.$ext'));
+      file.writeAsBytesSync(fileContents);
       JSaver.instance.save(
           fromPath: file.path,
           androidPathOptions: AndroidPathOptions(toDefaultDirectory: true)
       );
       messenger.showSnackBar(SnackBar(content: Text(localizations.success(exportSettings.defaultExportDir))));
     } else {
-      PlatformClient.shareFile(file.path, 'text/csv', '$filename.$ext');
+      PlatformClient.shareData(fileContents, 'text/csv', '$filename.$ext');
     }
   }
 
lib/platform_integration/platform_client.dart
@@ -39,4 +39,30 @@ class PlatformClient {
       return false;
     }
   }
+
+  /// Share binary data like a file.
+  ///
+  /// A file with the [data] will be created and shared with the specified [mimeType] through a
+  /// [Android Sharesheet](https://developer.android.com/training/sharing/send#using-android-system-sharesheet).
+  ///
+  /// The [mimeType] can be any string but should generally follow the `*/*` pattern. All official mime types can be
+  /// found here: https://mimetype.io/all-types
+  ///
+  /// The resulting file name is specified by [name].
+  ///
+  /// The returned value indicates whether a [PlatformException] was thrown.
+  ///
+  /// Using this over [shareFile] is more saves a file copy, when the data is present as binary data but not as a file.
+  static Future<bool> shareData(Uint8List data, String mimeType, String name) async {
+    try {
+      await _platformChannel.invokeMethod('shareData', {
+        'data': data,
+        'mimeType': mimeType,
+        'name': name
+      });
+      return true;
+    } on PlatformException {
+      return false;
+    }
+  }
 }
\ No newline at end of file