Flutter 编写 Android 特定代码

Flutter 提供了一个通用框架来访问平台特定的功能。 这使开发人员能够使用特定于平台的代码来扩展 Flutter 框架的功能。 可以通过框架轻松访问特定于平台的功能,如相机、电池电量、浏览器等。

访问平台特定代码的总体思路是通过简单的消息传递协议。 Flutter 代码、Client 和平台代码以及 Host 绑定到一个通用的 Message Channel。 客户端通过消息通道向主机发送消息。 主机监听消息通道,接收消息并执行必要的功能,最后通过消息通道将结果返回给客户端。

特定于平台的代码架构如下面的框图所示

flutter specific code architecture

消息传递协议使用标准消息编解码器(StandardMessageCodec 类),支持数字、字符串、布尔值等类似 JSON 的值的二进制序列化,序列化和反序列化在客户端和主机之间透明地工作。

让我们编写一个简单的应用程序来使用Android SDK打开浏览器并了解如何

在Android studio中新建一个Flutter应用,flutter_browser_app

用以下代码替换 main.dart 代码 -

import 'package:flutter/material.dart'; 
void main() => runApp(MyApp()); 
class MyApp extends StatelessWidget { 
   @override 
   Widget build(BuildContext context) {
      return MaterialApp(
         title: 'Flutter Demo', 
         theme: ThemeData( 
            primarySwatch: Colors.blue, 
         ), 
         home: MyHomePage(title: 'Flutter Demo Home Page'),
      );
   }
}
class MyHomePage extends StatelessWidget { 
   MyHomePage({Key key, this.title}) : super(key: key); 
   final String title; 
   
   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(
            title: Text(this.title), 
         ), 
         body: Center(
            child: RaisedButton( 
               child: Text('Open Browser'), 
               onPressed: null, 
            ), 
         ), 
      ); 
   }
}

在这里,我们创建了一个新按钮来打开浏览器并将其 onPressed 方法设置为 null。

现在,导入以下包

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

在这里,services.dart 包含调用平台特定代码的功能。

在 MyHomePage 小部件中创建一个新的消息通道。

static const platform = const 
MethodChannel('flutterapp.tutorialspoint.com/browser');

编写一个方法,_openBrowser,通过消息通道调用平台特定的方法,openBrowser 方法。

Future<void> _openBrowser() async { 
   try {
      final int result = await platform.invokeMethod(
         'openBrowser', <String, String>{ 
            'url': "https://flutter.dev" 
         }
      ); 
   } 
   on PlatformException catch (e) { 
      // Unable to open the browser 
      print(e); 
   }
}

在这里,我们使用了 platform.invokeMethod 来调用 openBrowser(在接下来的步骤中解释)。openBrowser 有一个参数 url 来打开一个特定的 url。

将 RaisedButton 的 onPressed 属性的值从 null 更改为 _openBrowser

onPressed: _openBrowser,

打开 MainActivity.java(在 android 文件夹内)并导入所需的库 -

import android.app.Activity; 
import android.content.Intent; 
import android.net.Uri; 
import android.os.Bundle; 

import io.flutter.app.FlutterActivity; 
import io.flutter.plugin.common.MethodCall; 
import io.flutter.plugin.common.MethodChannel; 
import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 
import io.flutter.plugin.common.MethodChannel.Result; 
import io.flutter.plugins.GeneratedPluginRegistrant;

写一个方法,openBrowser打开浏览器

private void openBrowser(MethodCall call, Result result, String url) { 
   Activity activity = this; 
   if (activity == null) { 
      result.error("ACTIVITY_NOT_AVAILABLE", 
      "Browser cannot be opened without foreground 
      activity", null); 
      return; 
   } 
   Intent intent = new Intent(Intent.ACTION_VIEW); 
   intent.setData(Uri.parse(url)); 
   
   activity.startActivity(intent); 
   result.success((Object) true); 
}

现在,在 MainActivity 类中设置通道名称 -

private static final String CHANNEL = "flutterapp.jiyik.com/browser";

编写 android 特定代码以在 onCreate 方法中设置消息处理 -

new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler( 
   new MethodCallHandler() { 
   @Override 
   public void onMethodCall(MethodCall call, Result result) { 
      String url = call.argument("url"); 
      if (call.method.equals("openBrowser")) {
         openBrowser(call, result, url); 
      } else { 
         result.notImplemented(); 
      } 
   } 
});

在这里,我们使用 MethodChannel 类创建了一个消息通道,并使用 MethodCallHandler 类来处理消息。onMethodCall 是负责通过检查消息调用正确的平台特定代码的实际方法。onMethodCall 方法从消息中提取 url,然后仅当方法调用为 openBrowser 时才调用 openBrowser。否则,它返回 notImplemented 方法。

该应用程序的完整源代码如下 -

MainActivity.java

package com.tutorialspoint.flutterapp.flutter_browser_app; 

import android.app.Activity; 
import android.content.Intent; 
import android.net.Uri; 
import android.os.Bundle; 
import io.flutter.app.FlutterActivity; 
import io.flutter.plugin.common.MethodCall; 
import io.flutter.plugin.common.MethodChannel.Result; 
import io.flutter.plugins.GeneratedPluginRegistrant; 

public class MainActivity extends FlutterActivity { 
   private static final String CHANNEL = "flutterapp.tutorialspoint.com/browser"; 
   @Override 
   protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      GeneratedPluginRegistrant.registerWith(this); 
      new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
         new MethodCallHandler() {
            @Override 
            public void onMethodCall(MethodCall call, Result result) {
               String url = call.argument("url"); 
               if (call.method.equals("openBrowser")) { 
                  openBrowser(call, result, url); 
               } else { 
                  result.notImplemented(); 
               }
            }
         }
      ); 
   }
   private void openBrowser(MethodCall call, Result result, String url) {
      Activity activity = this; if (activity == null) {
         result.error(
            "ACTIVITY_NOT_AVAILABLE", "Browser cannot be opened without foreground activity", null
         ); 
         return; 
      } 
      Intent intent = new Intent(Intent.ACTION_VIEW); 
      intent.setData(Uri.parse(url)); 
      activity.startActivity(intent); 
      result.success((Object) true); 
   }
}

main.dart

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

void main() => runApp(MyApp()); 
class MyApp extends StatelessWidget {
   @override 
   Widget build(BuildContext context) {
      return MaterialApp(
         title: 'Flutter Demo', 
         theme: ThemeData( 
            primarySwatch: Colors.blue, 
         ), 
         home: MyHomePage(
            title: 'Flutter Demo Home Page'
         ), 
      ); 
   }
}
class MyHomePage extends StatelessWidget {
   MyHomePage({Key key, this.title}) : super(key: key); 
   final String title; 
   static const platform = const MethodChannel('flutterapp.tutorialspoint.com/browser'); 
   Future<void> _openBrowser() async {
      try {
         final int result = await platform.invokeMethod('openBrowser', <String, String>{ 
            'url': "https://flutter.dev" 
         });
      }
      on PlatformException catch (e) { 
         // Unable to open the browser print(e); 
      } 
   }
   @override 
   Widget build(BuildContext context) {
      return Scaffold( 
         appBar: AppBar( 
            title: Text(this.title), 
         ), 
         body: Center(
            child: RaisedButton( 
               child: Text('Open Browser'), 
               onPressed: _openBrowser, 
            ), 
         ),
      );
   }
}

运行应用程序并单击 Open Browser 按钮,我们可以看到浏览器已启动。浏览器应用程序 - 主页如这里的屏幕截图所示

flutter demo home page

flutter productively build apps

查看笔记

扫码一下
查看教程更方便