I found a solution for android. This post should bundle all important steps into one. The things starting with YOUR_
are dependant on you. Change them accordingly.
First, you have to register the intent-filter
in the AndroidManifest.xml
. This will tell android to list your app as a possible option.
<!-- TODO: CHANGE ICON AND LABEL HERE -->
<intent-filter android:icon="YOUR_ICON_LOCATION"
android:label="YOUR_APP_LABEL"
android:priority="1">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="content" />
<data android:scheme="http" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<!-- TODO: CHANGE FILE EXTENSION -->
<data android:pathPattern=".*\\.YOUR_FILE_EXTENSION" />
</intent-filter>
Next, set up your Android Method Channel. For this, in Kotlin it is done like so:
import io.flutter.embedding.android.FlutterActivity
import android.content.Intent
import android.os.Bundle
import androidx.annotation.NonNull
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity : FlutterActivity() {
// TODO: CHANGE METHOD CHANNEL NAME
private val CHANNEL = "YOUR_CHANNEL_NAME"
var openPath: String? = null
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine)
val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
channel.setMethodCallHandler { call, result ->
when (call.method) {
"getOpenFileUrl" -> {
result.success(openPath)
}
else -> result.notImplemented()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleOpenFileUrl(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleOpenFileUrl(intent)
}
private fun handleOpenFileUrl(intent: Intent?) {
val path = intent?.data?.path
if (path != null) {
openPath = path
}
}
}
Finally, set up a handler on the dart side of things. The following code has to be in a drawn Widget. I placed it into my MainView
widget, as it is always drawn on app startup and is relatively high up in the Widget tree. (For me it is the first Widget outside the MaterialApp
Widget)
class MainView extends StatefulWidget {
const MainView({Key key}) : super(key: key);
@override
_MainViewState createState() => _MainViewState();
}
class _MainViewState extends State<MainView> with WidgetsBindingObserver {
// TODO: CHANGE CHANNEL NAME
static const platform = const MethodChannel("YOUR_CHANNEL_NAME");
@override
void initState() {
super.initState();
getOpenFileUrl();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
super.dispose();
WidgetsBinding.instance.removeObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
getOpenFileUrl();
}
}
@override
Widget build(BuildContext context) {
// TODO: Implement Build Method
}
void getOpenFileUrl() async {
dynamic url = await platform.invokeMethod("getOpenFileUrl");
if (url != null) {
setState(() {
// TODO: DO SOMETING WITH THE FILE URL
});
}
}
}
After completely killing and restarting both my app and the external app (in my case the file manager) it worked.