Android 开发者的 Flutter(五) —— Flutter 中的 Intent 及处理

声明:阅读该文章请确保你有 Android 开发的相关知识
这是《Android 开发者的 Flutter》系列的第五篇,如果想看上一篇请参考:
Android 开发者的 Flutter(四) —— Flutter 中自定义 Widget

Flutter 中的 Intent

在 Android 中,有两个主要的用例 Intent:在 Activity 之间进行导航以及与组件进行通信。另一方面,Flutter 没有 Intent 的概念,尽管您仍然可以通过本地集成(通过插件)启动 Intent。

Flutter 实际上并没有类似 Activity 和 Fragment; 然而,在 Flutter 中,使用 Navigator 和 Routes 在屏幕直接导航,这类似于 Activity。

Route 是应用程序的“屏幕”或“页面”的抽象,Navigator 是管理路线的 Widget。一条 Route 大致映射到 Activity,但它不是同一个意思。Navigator 可以 push 和 pop Routes 以从屏幕移动到屏幕。Navigator 的工作原理类似于堆栈,您可以在 Navigator 中 push() 新 Route 以便导航到目标,并且在您想“返回”时可以从 Navigator 中 pop() Route 以便返回。

与 Android 类似,您在 AndroidManifest.xml 声明您的 Activity,在Flutter中,您可以通过 Map 指定 Route 传递给顶级 MaterialApp 实例来声明所有 Routes:

void main() {
  runApp(new MaterialApp(
    home: new MyAppHome(), // becomes the route named '/'
    routes: <String, WidgetBuilder> {
      '/a': (BuildContext context) => new MyPage(title: 'page A'),
      '/b': (BuildContext context) => new MyPage(title: 'page B'),
      '/c': (BuildContext context) => new MyPage(title: 'page C'),
    },
  ));
}

然后,您可以通过获取的一个 Navigator 同时 push 声明的 Routes。

Navigator.of(context).pushNamed('/b');

Intents 的另一个流行用例是调用外部组件,例如 Camera 或 File picker。为此,您需要创建本地平台集成(或使用现有的插件)。

请参阅 [Flutter 插件] 了解如何构建本地平台集成。

如何处理来自外部应用程序的意图?

Flutter 可以通过直接与 Android 层交互并请求共享的数据处理来自其它 Android 程序传入的意图。

在这个例子中,我们在运行我们的 Flutter 代码的原生 Activity 上注册了文本共享 IntentFilter,所以其他应用程序可以共享文本到我们的 Flutter 应用程序。

基本流程意味着我们首先处理 Android 本地端(我们的 Activity)中的共享文本数据,然后等待 Flutter 通过 MethodChannel 请求数据。

首先,我们在 AndroidManifest.xml 中注册 Intent 过滤器,以便接收到我们想要处理的 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>

然后在 MainActivity 你可以处理 Intent,提取从 Intent 中共享的文本,并等待获取。当 Flutter 准备处理数据时,它将通过平台通道请求数据,然后我们可以从本机端发送它:

package com.yourcompany.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 MethodChannel.MethodCallHandler() {
        @Override
        public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
          if (methodCall.method.contentEquals("getSharedText")) {
            result.success(sharedText);
            sharedText = null;
          }
        }
      });
  }

  void handleSendText(Intent intent) {
    sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
  }
}

最后,您可以在呈现窗口 Widget 时从 Flutter 端请求数据:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(new SampleApp());
}

class SampleApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Sample Shared App Handler',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new SampleAppPage(),
    );
  }
}

class SampleAppPage extends StatefulWidget {
  SampleAppPage({Key key}) : super(key: key);

  @override
  _SampleAppPageState createState() => new _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 new Scaffold(body: new Center(child: new Text(dataShared)));
  }

  getSharedText() async {
    var sharedData = await platform.invokeMethod("getSharedText");
    if (sharedData != null) {
      setState(() {
        dataShared = sharedData;
      });
    }
  }
}

Flutter 中的 startActivityForResult()

在 Flutter 中,Naigator 类可以从 push 进堆栈的 Route 中获得结果。你可以通过使用 await 关键字的 push() 方法的回调中获取结果。

例如,如果您要让用户通过选择其位置的位置路线(Route),则可以执行以下操作:

Map coordinates = await Navigator.of(context).pushNamed('/location');

然后,在你的位置路线(Route)中,一旦用户选择了他们的位置,你就可以 pop 得到结果:

Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值