From 406dd73aac492b0f8ae8c62d126873e417f16f64 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Sat, 5 Jun 2021 10:09:45 -0300 Subject: [PATCH 1/2] Take screenshot and saved on the external storage of the device --- .../ArCoreAugmentedImagesView.kt | 5 + .../arcore_flutter_plugin/ArCoreView.kt | 5 + .../utils/ScreenshotsUtils.kt | 162 ++++++++++++++++++ example/lib/screens/assets_object.dart | 9 + example/lib/screens/hello_world.dart | 9 + .../screens/multiple_augmented_images.dart | 9 + example/pubspec.lock | 2 +- lib/src/arcore_controller.dart | 8 + 8 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/utils/ScreenshotsUtils.kt diff --git a/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/ArCoreAugmentedImagesView.kt b/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/ArCoreAugmentedImagesView.kt index 3f71637e..5f59be41 100644 --- a/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/ArCoreAugmentedImagesView.kt +++ b/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/ArCoreAugmentedImagesView.kt @@ -9,6 +9,7 @@ import android.util.Pair import com.difrancescogianmarco.arcore_flutter_plugin.flutter_models.FlutterArCoreNode import com.difrancescogianmarco.arcore_flutter_plugin.flutter_models.FlutterArCorePose import com.difrancescogianmarco.arcore_flutter_plugin.utils.ArCoreUtils +import com.difrancescogianmarco.arcore_flutter_plugin.utils.ScreenshotsUtils import com.google.ar.core.AugmentedImage import com.google.ar.core.AugmentedImageDatabase import com.google.ar.core.Config @@ -139,6 +140,10 @@ class ArCoreAugmentedImagesView(activity: Activity, context: Context, messenger: debugLog( "INIT AUGMENTED IMAGES") arScenViewInit(call, result) } + "takeScreenshot" -> { + debugLog(" Take screenshot...") + ScreenshotsUtils.onGetSnapshot(arSceneView,result,activity) + } "load_single_image_on_db" -> { debugLog( "load_single_image_on_db") val map = call.arguments as HashMap diff --git a/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/ArCoreView.kt b/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/ArCoreView.kt index 4928a935..df0d346c 100644 --- a/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/ArCoreView.kt +++ b/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/ArCoreView.kt @@ -16,6 +16,7 @@ import com.difrancescogianmarco.arcore_flutter_plugin.flutter_models.FlutterArCo import com.difrancescogianmarco.arcore_flutter_plugin.flutter_models.FlutterArCorePose import com.difrancescogianmarco.arcore_flutter_plugin.models.RotatingNode import com.difrancescogianmarco.arcore_flutter_plugin.utils.ArCoreUtils +import com.difrancescogianmarco.arcore_flutter_plugin.utils.ScreenshotsUtils import com.google.ar.core.* import com.google.ar.core.exceptions.CameraNotAvailableException import com.google.ar.core.exceptions.UnavailableException @@ -162,6 +163,10 @@ class ArCoreView(val activity: Activity, context: Context, messenger: BinaryMess "init" -> { arScenViewInit(call, result, activity) } + "takeScreenshot" -> { + debugLog(" Take screenshot...") + ScreenshotsUtils.onGetSnapshot(arSceneView,result,activity) + } "addArCoreNode" -> { debugLog(" addArCoreNode") val map = call.arguments as HashMap diff --git a/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/utils/ScreenshotsUtils.kt b/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/utils/ScreenshotsUtils.kt new file mode 100644 index 00000000..7c5779f1 --- /dev/null +++ b/android/src/main/kotlin/com/difrancescogianmarco/arcore_flutter_plugin/utils/ScreenshotsUtils.kt @@ -0,0 +1,162 @@ +package com.difrancescogianmarco.arcore_flutter_plugin.utils + +import java.nio.ByteBuffer +import java.io.File +import java.io.OutputStream +import java.io.FileOutputStream +import java.text.SimpleDateFormat +import java.util.Date +import android.content.pm.PackageManager; +import android.view.PixelCopy +import android.graphics.Canvas +import android.os.Handler +import android.os.Environment +import android.os.Build +import android.Manifest; +import android.graphics.Bitmap +import android.app.Activity +import android.util.Log +import io.flutter.plugin.common.MethodChannel +import com.google.ar.sceneform.ArSceneView + +class ScreenshotsUtils { + + companion object { + + fun getPictureName(): String { + + var sDate: String = SimpleDateFormat("yyyyMMddHHmmss").format(Date()); + + return "MyApp-" + sDate + ".png"; + } + + + fun saveBitmap(bitmap: Bitmap,activity: Activity): String { + + + val externalDir = Environment.getExternalStorageDirectory().getAbsolutePath(); + + val sDir = externalDir + File.separator + "MyApp"; + + val dir = File(sDir); + + val dirPath: String; + + if( dir.exists() || dir.mkdir()) { + dirPath = sDir + File.separator + getPictureName(); + } else { + dirPath = externalDir + File.separator + getPictureName(); + } + + + + try{ + + val file = File(dirPath) + + // Get the file output stream + val stream: OutputStream = FileOutputStream(file) + + // Compress bitmap + bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream) + + // Flush the stream + stream.flush() + + // Close stream + stream.close() + + + }catch (e: Exception){ + e.printStackTrace() + } + + + return dirPath; + + + + } + + fun permissionToWrite(activity: Activity): Boolean { + + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + Log.i("Sreenshot", "Permission to write false due to version codes."); + + return false; + } + + var perm = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); + + if(perm == PackageManager.PERMISSION_GRANTED) { + Log.i("Sreenshot", "Permission to write granted!"); + + return true; + } + + Log.i("Sreenshot","Requesting permissions..."); + activity.requestPermissions( + arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), + 11 + ); + Log.i("Sreenshot", "No permissions :("); + + return false; + } + + + fun onGetSnapshot(arSceneView: ArSceneView?, result: MethodChannel.Result,activity: Activity){ + + if( !permissionToWrite(activity) ) { + Log.i("Sreenshot", "Permission to write files missing!"); + + result.success(null); + + return; + } + + if(arSceneView == null){ + Log.i("Sreenshot", "Ar Scene View is NULL!"); + + result.success(null); + + return; + } + + + try { + + val view = arSceneView!!; + + val bitmapImage: Bitmap = Bitmap.createBitmap( + view.getWidth(), + view.getHeight(), + Bitmap.Config.ARGB_8888 + ); + Log.i("Sreenshot", "PixelCopy requesting now..."); + PixelCopy.request(view, bitmapImage, { copyResult -> + if (copyResult == PixelCopy.SUCCESS) { + Log.i("Sreenshot", "PixelCopy request SUCESS. ${copyResult}"); + + var pathSaved: String = saveBitmap(bitmapImage,activity); + + Log.i("Sreenshot", "Saved on path: ${pathSaved}"); + result.success(pathSaved); + + }else{ + Log.i("Sreenshot", "PixelCopy request failed. ${copyResult}"); + result.success(null); + } + + }, + Handler()); + + } catch (e: Exception){ + + e.printStackTrace() + } + + + } + } +} \ No newline at end of file diff --git a/example/lib/screens/assets_object.dart b/example/lib/screens/assets_object.dart index b9d627ea..5c465c40 100644 --- a/example/lib/screens/assets_object.dart +++ b/example/lib/screens/assets_object.dart @@ -34,6 +34,15 @@ class _AssetsObjectState extends State { ), ], ), + floatingActionButton: FloatingActionButton( + onPressed: () async { + String path = await arCoreController.snapshot(); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Photo saved on $path"),)); + + }, + child: const Icon(Icons.photo), + backgroundColor: Colors.green, + ), ), ); } diff --git a/example/lib/screens/hello_world.dart b/example/lib/screens/hello_world.dart index f91b4883..9c5cf2ea 100644 --- a/example/lib/screens/hello_world.dart +++ b/example/lib/screens/hello_world.dart @@ -21,6 +21,15 @@ class _HelloWorldState extends State { body: ArCoreView( onArCoreViewCreated: _onArCoreViewCreated, ), + floatingActionButton: FloatingActionButton( + onPressed: () async { + String path = await arCoreController.snapshot(); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Photo saved on $path"),)); + + }, + child: const Icon(Icons.photo), + backgroundColor: Colors.green, + ), ), ); } diff --git a/example/lib/screens/multiple_augmented_images.dart b/example/lib/screens/multiple_augmented_images.dart index 53e06d27..358bf0cb 100644 --- a/example/lib/screens/multiple_augmented_images.dart +++ b/example/lib/screens/multiple_augmented_images.dart @@ -28,6 +28,15 @@ class _MultipleAugmentedImagesPageState onArCoreViewCreated: _onArCoreViewCreated, type: ArCoreViewType.AUGMENTEDIMAGES, ), + floatingActionButton: FloatingActionButton( + onPressed: () async { + String path = await arCoreController.snapshot(); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Photo saved on $path"),)); + + }, + child: const Icon(Icons.photo), + backgroundColor: Colors.green, + ), ), ); } diff --git a/example/pubspec.lock b/example/pubspec.lock index 5198b81b..a8ae4cc0 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: path: ".." relative: true source: path - version: "0.0.10" + version: "0.0.11" async: dependency: transitive description: diff --git a/lib/src/arcore_controller.dart b/lib/src/arcore_controller.dart index c1e1a78e..7e962b79 100644 --- a/lib/src/arcore_controller.dart +++ b/lib/src/arcore_controller.dart @@ -258,4 +258,12 @@ class ArCoreController { print(ex); } } + + Future snapshot() async { + + final String path = await _channel.invokeMethod('takeScreenshot'); + + return path; + } + } From a5da21795ad37e3beec16af232ef32b7aaf3903f Mon Sep 17 00:00:00 2001 From: Eduardo Date: Sat, 5 Jun 2021 12:39:30 -0300 Subject: [PATCH 2/2] finish --- android/src/main/AndroidManifest.xml | 4 +++- example/lib/screens/hello_world.dart | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index a1215c10..c45be6ec 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ package="com.difrancescogianmarco.arcore_flutter_plugin"> + + - + diff --git a/example/lib/screens/hello_world.dart b/example/lib/screens/hello_world.dart index 9c5cf2ea..505a01fb 100644 --- a/example/lib/screens/hello_world.dart +++ b/example/lib/screens/hello_world.dart @@ -2,6 +2,7 @@ import 'package:arcore_flutter_plugin/arcore_flutter_plugin.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:vector_math/vector_math_64.dart' as vector; +import 'dart:io'; class HelloWorld extends StatefulWidget { @override @@ -24,8 +25,6 @@ class _HelloWorldState extends State { floatingActionButton: FloatingActionButton( onPressed: () async { String path = await arCoreController.snapshot(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Photo saved on $path"),)); - }, child: const Icon(Icons.photo), backgroundColor: Colors.green,