Android 开发者的 Flutter 指南 — Intent

2019-02-25  本文已影响15人  敲代码的本愿

Intent 在 Flutter 中对应什么?

Flutter 没有 Intent 的概念,但仍可通过插件间接使用。

通过 Navigator 和 Route 跳转页面,且都在同一 Activity 。
Route: 理解为页面。类似于 Activity ,但含义不同。
Navigator: 用来管理 Route 的 Widget ,通过 push() 跳转或 pop() 回退。

页面跳转的方式:

  1. MaterialApp:指定 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.of(context).pushNamed('/b');
  1. WidgetApp:直接导航到一个 route。

要在 Flutter 中使用类似 Intent 调用外部组件,如相机、相册的功能,则需要在本地平台中集成,或使用现有插件

关于创建本地集成平台,参阅 Developing Packages and Plugins

如何处理来自外部程序的 Intent ?

Flutter 可以直接通过来自 Android 的 Intent 与 Android 层进行交互并请求共享数据。

下面示例,在一个运行 Flutter 代码的本地 activity 中注册一个分享文本的 Intent 过滤器,然后其他应用可以与 Flutter 应用分享文本。

基本流程,首先在 Android 本地(Activiy)处理分享的文本数据,然后等待 Flutter 请求数据,并使用 MethodChannel 返回给 Flutter。

  1. 在 AndroidManifest.xml 中为所有 Intent 注册过滤器:
<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>
  1. 在 MainActivity 中处理 Intent,获取共享文本数据,并持有它。当 Flutter 请求数据时,从本地端发送过去:
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.plugin.common.MethodChannel.MethodCallHandler;
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);
  }
}
  1. 当 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;
      });
    }
  }
}

startActivityForResult() 对应什么 ?

通过等待(await) Navigator 的 push() 方法获取返回结果。

示例:

//跳转 location 页面
Map coordinates = await Navigator.of(context).pushNamed('/location');

//在 location 页面,通过 pop方法返回结果
Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});

原文给 Android 开发者的 Flutter 指南,参考 Android 开发者参考
此文目的:仅与 Android 对比,尽可能言简意骇的翻译,且不遗漏、不曲解词义。

上一篇 下一篇

猜你喜欢

热点阅读