Flattern - Schreiben von Android-spezifischem Code

Flutter bietet einen allgemeinen Rahmen für den Zugriff auf plattformspezifische Funktionen. Dadurch kann der Entwickler die Funktionalität des Flutter- Frameworks mithilfe von plattformspezifischem Code erweitern. Auf plattformspezifische Funktionen wie Kamera, Akkuladestand, Browser usw. kann über das Framework problemlos zugegriffen werden.

Die allgemeine Idee für den Zugriff auf den plattformspezifischen Code besteht in einem einfachen Messaging-Protokoll. Flattercode, Client und Plattformcode sowie Host werden an einen gemeinsamen Nachrichtenkanal gebunden. Der Client sendet eine Nachricht über den Nachrichtenkanal an den Host. Der Host hört auf den Nachrichtenkanal, empfängt die Nachricht und führt die erforderlichen Funktionen aus. Anschließend gibt er das Ergebnis über den Nachrichtenkanal an den Client zurück.

Die plattformspezifische Codearchitektur ist im folgenden Blockdiagramm dargestellt.

Das Messaging-Protokoll verwendet einen Standard-Nachrichtencodec (StandardMessageCodec-Klasse), der die binäre Serialisierung von JSON-ähnlichen Werten wie Zahlen, Zeichenfolgen, Booleschen Werten usw. unterstützt. Die Serialisierung und De-Serialisierung funktioniert transparent zwischen dem Client und dem Host.

Lassen Sie uns eine einfache Anwendung schreiben, um einen Browser mit Android SDK zu öffnen und zu verstehen, wie

  • Erstellen Sie eine neue Flutter-Anwendung in Android Studio, flutter_browser_app

  • Ersetzen Sie den main.dart-Code durch den folgenden Code -

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, 
            ), 
         ), 
      ); 
   }
}
  • Hier haben wir eine neue Schaltfläche erstellt, um den Browser zu öffnen und die onPressed-Methode auf null zu setzen.

  • Importieren Sie nun die folgenden Pakete:

import 'dart:async'; 
import 'package:flutter/services.dart';
  • Hier enthält services.dart die Funktionalität zum Aufrufen von plattformspezifischem Code.

  • Erstellen Sie einen neuen Nachrichtenkanal im MyHomePage-Widget.

static const platform = const 
MethodChannel('flutterapp.tutorialspoint.com/browser');
  • Schreiben Sie eine Methode, _openBrowser, um die plattformspezifische Methode aufzurufen, openBrowser-Methode über den Nachrichtenkanal.

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); 
   }
}

Hier haben wir platform.invokeMethod verwendet, um openBrowser aufzurufen (wird in den folgenden Schritten erläutert). openBrowser hat ein Argument, URL, um eine bestimmte URL zu öffnen.

  • Ändern Sie den Wert der onPressed-Eigenschaft des RaisedButton von null in _openBrowser.

onPressed: _openBrowser,
  • Öffnen Sie MainActivity.java (im Android-Ordner) und importieren Sie die gewünschte Bibliothek -

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;
  • Schreiben Sie eine Methode, openBrowser, um einen Browser zu öffnen

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); 
}
  • Legen Sie nun den Kanalnamen in der MainActivity-Klasse fest -

private static final String CHANNEL = "flutterapp.tutorialspoint.com/browser";
  • Schreiben Sie androidspezifischen Code, um die Nachrichtenbehandlung in der onCreate-Methode festzulegen.

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(); 
      } 
   } 
});

Hier haben wir einen Nachrichtenkanal mit der MethodChannel-Klasse erstellt und die MethodCallHandler-Klasse verwendet, um die Nachricht zu verarbeiten. onMethodCall ist die eigentliche Methode, die dafür verantwortlich ist, den richtigen plattformspezifischen Code durch Überprüfen der Nachricht aufzurufen. Die onMethodCall-Methode extrahiert die URL aus der Nachricht und ruft den openBrowser nur auf, wenn der Methodenaufruf openBrowser lautet. Andernfalls wird die notImplemented-Methode zurückgegeben.

Der vollständige Quellcode der Anwendung lautet wie folgt:

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

Führen Sie die Anwendung aus und klicken Sie auf die Schaltfläche Browser öffnen. Sie können sehen, dass der Browser gestartet ist. Die Browser-App - Homepage ist wie im Screenshot hier gezeigt -