文档地址:https://flutter.io/docs/get-started/flutter-for/android-devs
译者:Haocxx
Intent
在Flutter中,Intent等于什么?
在Android中,Intent主要有两个作用:在不同Activity之间跳转,以及组件之间的通信。在Flutter中其实并没有Intent的概念,即使你仍然可以集成使用一个AndroidIntent的插件(https://pub.dartlang.org/packages/android_intent)。
Flutter中并没有那么多的Activity和Fragment,如果要跳转页面的话,是通过Navigator和Route来实现的。
Route是对一个APP页面的抽象,而Navigator是管理Route的组件,一个Route可以认为对应了一个Activity。Navigator可以通过pop和push来讲Route移入或移出屏幕。Navigator就像一个栈一样,你可以调用push()来将你想要跳转的Route移入栈顶,也可以调用pop()将栈顶的Route移出(比如返回键的逻辑)。
在Android中,Acitivity被生命在AndroidManifest.xml文件中.
在Flutter中,可以用两步来实现页面的跳转:首先定义一个Route的Map表,然后就可以通过Navigator直接跳转了。
如下定义一个Route Map:
void main() {
runApp(MaterialApp(
home: MyAppHome(), // becomes the route named '/'
routes: <String, WidgetBuilder> {
'/a': (BuildContext context) => MyPage(title: 'page A'),
'/b': (BuildContext context) => MyPage(title: 'page B'),
'/c': (BuildContext context) => MyPage(title: 'page C'),
},
));
}
通过向Navigator传递一个Route的name key来跳转页面:
Navigator.of(context).pushNamed('/b');
Intent还有其他用法比如调用像相机,文件选择器之类的外部组件。对于这种实现,你需要创建一个native集成或使用已有的库。具体方法参见:https://flutter.io/docs/development/packages-and-plugins/developing-packages
如何在Flutter中处理外部应用传入的Intent?
Flutter可以通过直接与Android应用层通信并获取Intent中的信息来处理从Android原生中传入的Intent。
下面的例子中,为运行在Flutter下的Android原生Activity注册了一个文本共享的intent-filter,其他的APP可以与我们的Flutter APP共享文本。
这个程序的基本流程是先在Android原生端处理文本数据,然后等待Flutter请求数据,通过MethodChannel发送。
首先,在AndroidManifest里面注册intent-filter:
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- ... -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
然后在MainActivity中处理数据,持有Intent中的text数据。当Flutter准备就绪,就可以通过native方法来获取数据了:
package com.example.shared;
import android.content.Intent;
import android.os.Bundle;
import java.nio.ByteBuffer;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.ActivityLifecycleListener;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
private String sharedText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent); // Handle text being sent
}
}
new MethodChannel(getFlutterView(), "app.channel.shared.data").setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.contentEquals("getSharedText")) {
result.success(sharedText);
sharedText = null;
}
}
});
}
void handleSendText(Intent intent) {
sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
}
}
最后,在Flutter的Widget渲染的时候去请求数据:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample Shared App Handler',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
static const platform = const MethodChannel('app.channel.shared.data');
String dataShared = "No data";
@override
void initState() {
super.initState();
getSharedText();
}
@override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: Text(dataShared)));
}
getSharedText() async {
var sharedData = await platform.invokeMethod("getSharedText");
if (sharedData != null) {
setState(() {
dataShared = sharedData;
});
}
}
}
在Flutter中,如何实现startActivityForResult的效果?
在Flutter中,Navigator类在跳转Route,push到栈时可以获取一个返回值,由push()方法返回。
比如,跳转一个叫“/location”的Route让用户选择位置信息,可以这样做:
Map coordinates = await Navigator.of(context).pushNamed('/location');
然后,在选择位置Route当中,在用户选定了位置之后,可以这样讲Route移出栈并返回结果:
Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});