Flutter Library: Media Scanner
- Published on
- Authors
- Name
- Mudassir
- Github
- @Lzyct
Background
By default, in Android when you create a new Image/Video, you need to run MediaScannerConnection to show Image/Video on your Gallery. And that should be an issue when you create new Image/Video on Flutter using image_picker because that library not reload the Media and make your Image/Video not showing on your Gallery.
Bridge code from Flutter to Android
When you're working on Flutter project and need to do something in Android Native side, you can use Platform Channel. And you need to register it in your pubspec.yaml, for more detail you can check here. Or maybe I will create a specific post about How to create a library on Flutter.
After you read the instruction about how to create plugin on Flutter, we can start to create plugin on Flutter but in this case we will only work on Android Platform since this issue only happen on Android.
Flutter communicate with Android native from this method
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "media_scanner")
channel.setMethodCallHandler(this)
context = flutterPluginBinding.applicationContext
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "refreshGallery") {
val path: String? = call.argument("path")
result.success(refreshMedia(path))
} else {
result.notImplemented()
}
}
media_scanner
is Method channel name. We define specific name for method channel to communicate from Dart to Kotlin. And we're using method name (refreshGallery
) to run a specific function when that method name triggered. We also can pass some arguments, because we need full path for Image/Video we pass that value.
Re-Scan all media on Android Device
On Android, with API below 28, we can use context.sendBroadcast
with Intent.ACTION_MEDIA_SCANNER_SCAN_FILE
to refresh media files. But after API 28 that method is deprecated we need to update the code and start using MediaScannerConnection.
result.success(refreshMedia(path))
on result.success we call refreshMedia
method, that's method will execute a function to refresh media library
private fun refreshMedia(path: String?): String {
return try {
/// Throw NPE if path is empty/null
if (path == null)
throw NullPointerException()
val file = File(path)
/// Check if still using sendBroadcast or MediaScannerConnection
if (android.os.Build.VERSION.SDK_INT < 29) {
context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)))
} else {
MediaScannerConnection.scanFile(context, arrayOf(file.toString()),
arrayOf(file.name), null)
}
Log.d("Media Scanner", "Success show image $path in Gallery")
"Success show image $path in Gallery" } catch (e: Exception) {
Log.e("Media Scanner", e.toString())
e.toString()
}
}
And from Dart we create class to access Kotlin code
import 'dart:async';
import 'package:flutter/services.dart';
class MediaScanner {
/// Define Method Channel
static const MethodChannel _channel = const MethodChannel('media_scanner');
/// Path : Path of Image/Video
static Future<String?> loadMedia({String? path}) async =>
await _channel.invokeMethod('refreshGallery', {"path": path});
}
Use Library from pub.dev
You can save your time and just use my library media_scanner
add my library to your pubspec.yaml
media_scanner: ^2.1.0 // use latest version
and you can use it just simple like this
import 'package:media_scanner/media_scanner.dart';
...
MediaScanner.loadMedia(path: filePath);
...