diff --git a/android/build.gradle b/android/build.gradle
index bd8fd63..6ec925a 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -20,6 +20,7 @@ rootProject.allprojects {
}
apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
android {
compileSdkVersion 30
@@ -32,3 +33,10 @@ android {
disable 'InvalidPackage'
}
}
+dependencies {
+ implementation "androidx.core:core-ktx:+"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
+repositories {
+ mavenCentral()
+}
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 3afbad6..31eb36d 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -2,5 +2,5 @@
package="com.flutter.moum.screenshot_callback">
-
+
diff --git a/android/src/main/java/com/flutter/moum/screenshot_callback/Path.java b/android/src/main/java/com/flutter/moum/screenshot_callback/Path.java
deleted file mode 100644
index 4d14724..0000000
--- a/android/src/main/java/com/flutter/moum/screenshot_callback/Path.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.flutter.moum.screenshot_callback;
-
-import android.os.Environment;
-
-import java.io.File;
-
-public enum Path {
- DCIM(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "Screenshots" + File.separator),
- PICTURES(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES ) + File.separator + "Screenshots" + File.separator);
-
- final private String path;
-
- public String getPath() {
- return path;
- }
-
- private Path(String path) {
- this. path = path;
-
- }
-}
diff --git a/android/src/main/java/com/flutter/moum/screenshot_callback/ScreenshotCallbackPlugin.java b/android/src/main/java/com/flutter/moum/screenshot_callback/ScreenshotCallbackPlugin.java
index 4329f2b..c19f9ee 100644
--- a/android/src/main/java/com/flutter/moum/screenshot_callback/ScreenshotCallbackPlugin.java
+++ b/android/src/main/java/com/flutter/moum/screenshot_callback/ScreenshotCallbackPlugin.java
@@ -1,87 +1,70 @@
package com.flutter.moum.screenshot_callback;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function1;
-import android.os.Build;
-import android.os.FileObserver;
-
-import android.os.Handler;
-import android.os.Looper;
//import android.util.Log;
-import java.io.File;
-import java.util.List;
-import java.util.ArrayList;
-
public class ScreenshotCallbackPlugin implements MethodCallHandler {
- private static MethodChannel channel;
+ ScreenshotCallbackPlugin(Context context) {
+ _context = context;
+ }
+
+ private static MethodChannel _channel;
+ private static final String _tag = "screenshot_callback";
- private Handler handler;
- private FileObserver fileObserver;
- private String TAG = "tag";
+ private final Context _context;
+ private Handler _handler;
+ private ScreenshotDetector _detector;
+ private String _lastScreenshotName;
public static void registerWith(Registrar registrar) {
- channel = new MethodChannel(registrar.messenger(), "flutter.moum/screenshot_callback");
- channel.setMethodCallHandler(new ScreenshotCallbackPlugin());
+ _channel = new MethodChannel(registrar.messenger(), "flutter.moum/screenshot_callback");
+ _channel.setMethodCallHandler(new ScreenshotCallbackPlugin(registrar.context()));
}
@Override
public void onMethodCall(MethodCall call, Result result) {
- //Log.d(TAG, "onMethodCall: ");
-
if (call.method.equals("initialize")) {
- handler = new Handler(Looper.getMainLooper());
- if (Build.VERSION.SDK_INT >= 29) {
- //Log.d(TAG, "android x");
- List files = new ArrayList();
- for (Path path : Path.values()) {
- files.add(new File(path.getPath()));
- }
+ _handler = new Handler(Looper.getMainLooper());
- fileObserver = new FileObserver(files, FileObserver.CREATE) {
- @Override
- public void onEvent(int event, String path) {
- //Log.d(TAG, "androidX onEvent");
- if (event == FileObserver.CREATE) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- channel.invokeMethod("onCallback", null);
- }
- });
- }
- }
- };
- fileObserver.startWatching();
- } else {
- //Log.d(TAG, "android others");
- for (Path path : Path.values()) {
- //Log.d(TAG, "onMethodCall: "+path.getPath());
- fileObserver = new FileObserver(path.getPath(), FileObserver.CREATE) {
- @Override
- public void onEvent(int event, String path) {
- //Log.d(TAG, "android others onEvent");
- if (event == FileObserver.CREATE) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- channel.invokeMethod("onCallback", null);
- }
- });
+ _detector = new ScreenshotDetector(_context, new Function1() {
+ @Override
+ public Unit invoke(String screenshotName) {
+// Log.d(_tag, "onScreenshotDetected: " + screenshotName);
+
+ if (!screenshotName.equals(_lastScreenshotName)) {
+ _lastScreenshotName = screenshotName;
+ _handler.post(new Runnable() {
+ @Override
+ public void run() {
+// Log.d(_tag, "onCallback: ");
+ _channel.invokeMethod("onCallback", null);
}
- }
- };
- fileObserver.startWatching();
+ });
+ }
+
+ return null;
}
- }
+ });
+ _detector.start();
+
result.success("initialize");
} else if (call.method.equals("dispose")) {
- fileObserver.stopWatching();
+ _detector.stop();
+ _detector = null;
+ _lastScreenshotName = null;
+
result.success("dispose");
} else {
result.notImplemented();
diff --git a/android/src/main/java/com/flutter/moum/screenshot_callback/ScreenshotDetector.kt b/android/src/main/java/com/flutter/moum/screenshot_callback/ScreenshotDetector.kt
new file mode 100644
index 0000000..0f4a64e
--- /dev/null
+++ b/android/src/main/java/com/flutter/moum/screenshot_callback/ScreenshotDetector.kt
@@ -0,0 +1,111 @@
+package com.flutter.moum.screenshot_callback
+
+import android.content.ContentResolver
+import android.content.Context
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Build
+import android.os.Handler
+import android.os.Looper
+import android.provider.MediaStore
+
+class ScreenshotDetector(private val context: Context,
+ private val callback: (name: String) -> Unit) {
+
+ private var contentObserver: ContentObserver? = null
+
+ fun start() {
+ if (contentObserver == null) {
+ contentObserver = context.contentResolver.registerObserver()
+ }
+ }
+
+ fun stop() {
+ contentObserver?.let { context.contentResolver.unregisterContentObserver(it) }
+ contentObserver = null
+ }
+
+ private fun reportScreenshotsUpdate(uri: Uri) {
+ val screenshots: List = queryScreenshots(uri)
+ if (screenshots.isNotEmpty()) {
+ callback.invoke(screenshots.last());
+ }
+ }
+
+ private fun queryScreenshots(uri: Uri): List {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ queryRelativeDataColumn(uri)
+ } else {
+ queryDataColumn(uri)
+ }
+ }
+
+ private fun queryDataColumn(uri: Uri): List {
+ val screenshots = mutableListOf()
+
+ val projection = arrayOf(
+ MediaStore.Images.Media.DATA
+ )
+ context.contentResolver.query(
+ uri,
+ projection,
+ null,
+ null,
+ null
+ )?.use { cursor ->
+ val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
+
+ while (cursor.moveToNext()) {
+ val path = cursor.getString(dataColumn)
+ if (path.contains("screenshot", true)) {
+ screenshots.add(path)
+ }
+ }
+ }
+
+ return screenshots
+ }
+
+ private fun queryRelativeDataColumn(uri: Uri): List {
+ val screenshots = mutableListOf()
+
+ val projection = arrayOf(
+ MediaStore.Images.Media.DISPLAY_NAME,
+ MediaStore.Images.Media.RELATIVE_PATH
+ )
+ context.contentResolver.query(
+ uri,
+ projection,
+ null,
+ null,
+ null
+ )?.use { cursor ->
+ val relativePathColumn =
+ cursor.getColumnIndex(MediaStore.Images.Media.RELATIVE_PATH)
+ val displayNameColumn =
+ cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
+ while (cursor.moveToNext()) {
+ val name = cursor.getString(displayNameColumn)
+ val relativePath = cursor.getString(relativePathColumn)
+ if (name.contains("screenshot", true) or
+ relativePath.contains("screenshot", true)
+ ) {
+ screenshots.add(name)
+ }
+ }
+ }
+
+ return screenshots
+ }
+
+ private fun ContentResolver.registerObserver(): ContentObserver {
+ val contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
+ override fun onChange(selfChange: Boolean, uri: Uri?) {
+ super.onChange(selfChange, uri)
+ uri?.let { reportScreenshotsUpdate(it) }
+ }
+ }
+ registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, contentObserver)
+ return contentObserver
+ }
+}
\ No newline at end of file
diff --git a/example/android/build.gradle b/example/android/build.gradle
index 6de3728..24ab9b4 100644
--- a/example/android/build.gradle
+++ b/example/android/build.gradle
@@ -1,4 +1,5 @@
buildscript {
+ ext.kotlin_version = '1.5.0'
repositories {
google()
jcenter()
@@ -6,6 +7,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
diff --git a/example/pubspec.lock b/example/pubspec.lock
index c5d0564..d95a3c1 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -87,14 +87,14 @@ packages:
name: permission_handler
url: "https://pub.dartlang.org"
source: hosted
- version: "5.0.1+1"
+ version: "5.1.0+2"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.1"
+ version: "2.0.2"
plugin_platform_interface:
dependency: transitive
description:
diff --git a/pubspec.lock b/pubspec.lock
index 02f6f7c..35e329b 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -87,14 +87,14 @@ packages:
name: permission_handler
url: "https://pub.dartlang.org"
source: hosted
- version: "5.0.1+1"
+ version: "5.1.0+2"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.1"
+ version: "2.0.2"
plugin_platform_interface:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index c37b05e..5163dfa 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -10,7 +10,7 @@ environment:
dependencies:
flutter:
sdk: flutter
- permission_handler: ^5.0.1+1
+ permission_handler: ^5.1.0+2
dev_dependencies:
flutter_test: