/**/

Flutter - 编写Android代码

首页 / Flutter入门教程 / Flutter - 编写Android代码

Flutter提供了访问平台特定函数的通用框架,这使开发人员可以使用平台特定的代码扩展 Flutter 框架的函数,可以通过框架轻松访问平台特定的函数,例如相机,电池电量,浏览器等。

访问平台特定代码的总体思路是通过简单的消息传递协议,Flutter代码,客户端和平台代码以及主机绑定到公共消息通道。客户端通过消息通道向主机发送消息。主机在消息通道上侦听,接收消息并执行必要的函数,最后通过消息通道将输出返回给客户端。

特定于平台的代码架构显示在下面的框图中-

Specific Code Architecture

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

下表显示了如何在Android和iOS平台上接收Dart

dartandroidios
nullnull无(嵌套时为NSNull)
booljava.lang.BooleanNSNumber numberWithBool:
intjava.lang.IntegerNSNumber numberWithInt:
doublejava.lang.DoubleNSNumber numberWithDouble:
Stringjava.lang.StringNSString:
Uint8Listbyte[]FlutterStandardTypedData typedDataWithBytes:
Int32Listint[]FlutterStandardTypedData typedDataWithInt32:
Int64Listlong[]FlutterStandardTypedData typedDataWithInt64:
Float64Listdouble[]FlutterStandardTypedData typedDataWithFloat64:
Listjava.util.ArrayListNSArray
Mapjava.util.HashMapNSDictionary

让无涯教程编写一个简单的应用程序,以使用 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 Widget中创建一个新的消息通道。

static const platform = const MethodChannel('flutterapp.learnfk.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) { 
      //无法打开浏览器
      print(e); 
   }
}

在这里,无涯教程使用platform.invokeMethod调用openBrowser(在后续步骤中进行了说明)。 openBrowser有一个参数,URL以打开特定的URL。

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.learnfk.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.learnfk.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.learnfk.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.learnfk.com/browser'); 
   Future<void> _openBrowser() async {
      try {
         final int result = await platform.invokeMethod('openBrowser', <String, String>{ 
            'url': "https://flutter.dev" 
         });
      }
      on PlatformException catch (e) { 
         //无法打开浏览器打印(e);
      } 
   }
   @override 
   Widget build(BuildContext context) {
      return Scaffold( 
         appBar: AppBar( 
            title: Text(this.title), 
         ), 
         body: Center(
            child: RaisedButton( 
               child: Text('Open Browser'), 
               onPressed: _openBrowser, 
            ), 
         ),
      );
   }
}

运行该应用程序,然后单击"打开浏览器"按钮,您可以看到浏览器已启动。浏览器应用程序-主页如此处的屏幕截图所示-

Flutter Demo Home PageProductively Build Apps

这一章《Flutter - 编写Android代码》你学到了什么?在下面做个笔记吧!做站不易,你的分享是对我们最大的支持

好记忆不如烂笔头。留下你的足迹吧 :)

猜你喜欢

技术与商业案例解读 -〔徐飞〕

许式伟的架构课 -〔许式伟〕

说透敏捷 -〔宋宁〕

流程型组织15讲 -〔蒋伟良〕

Getx Flutter 在更新值时抛出空错误

在 flutter 中使用 Firebase 实时数据库数据创建无限滚动效果

如何在 ListView.builder 中扩展文本?

使用 hydrad_bloc 的预览包

Flutter Bloc Todo 示例 - 收听存储库中的单个 todo

在 Flutter 中更新对象实例属性的最佳实践是什么?该实例嵌套在提供程序类的映射中,如下所示

视频教程

Flutter - 95.动画(上) 更多视频教程 »