Flutter - 編寫Android特定程式碼



Flutter提供了一個通用的框架來訪問平臺特定的功能。這使開發人員能夠使用平臺特定的程式碼擴充套件Flutter框架的功能。可以透過該框架輕鬆訪問平臺特定的功能,例如相機、電池電量、瀏覽器等。

訪問平臺特定程式碼的一般思路是透過簡單的訊息傳遞協議。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.club.tw" 
         }
      ); 
   } 
   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.tutorialspoint.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方法。

應用程式的完整原始碼如下:

main.dart

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.club.tw" 
         });
      }
      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, 
            ), 
         ),
      );
   }
}

執行應用程式並單擊“開啟瀏覽器”按鈕,您會看到瀏覽器啟動。瀏覽器應用程式 - 首頁截圖如下:

Flutter Demo Home Page

Productively Build Apps
廣告
© . All rights reserved.