How is this code structure generated?

Development environment: AndroidStudio3.5

I tried this in the old version, which would just import the module, like this:

flutter create -t module flutter_module3
Copy the code

2, Modify Android project settings.gradle file

include ':app'
rootProject.name='My Application'// Add the following configurationsetBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir.parentFile,
        'flutter_module3/.android/include_flutter.groovy'
))

Copy the code

3. Modify the build.gradle file in app

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx. Appcompat: appcompat: 1.0.2'
    implementation 'androidx. Core: the core - KTX: 1.0.2'
    implementation 'androidx. Constraintlayout: constraintlayout: 1.1.3'
    testImplementation 'junit: junit: 4.12'
    androidTestImplementation 'androidx. Test. Ext: junit: 1.1.0'
    androidTestImplementation 'androidx. Test. Espresso: espresso - core: 3.1.1'// implement Project (':flutter')}Copy the code

Channels are of three types: MethodChannel, EventChannel, and BasicMessageChannel

BasicMessageChannel usage

Android can send messages to flutter and receive the return value of flutter. Flutter can send messages to Android, but cannot receive the return value.

Core code: Android terminal

final BasicMessageChannel messageChannel = new BasicMessageChannel<>(flutterView, CHANNEL, StringCodec.INSTANCE);
        messageChannel.
                setMessageHandler(new BasicMessageChannel.MessageHandler<String>() { public void onMessage(String s, BasicMessageChannel. Reply < String > Reply) {/ / receiving to flutter active messages sent the tv2. The setText (s); // This is returned to flutter, but flutter cannot receive reply. Reply ("Android has received the message."); }}); tv.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                messageChannel.send("Here's a message from Android to you.");

                messageChannel.send("Here's a message from Android to you.",new BasicMessageChannel.Reply(){ @Override public void reply(Object o) { tv3.setText(o.toString()); }}); }});Copy the code

The flutter end:

class HomePageBasicMessageChannel extends StatefulWidget
{
  @override
  State<StatefulWidget> createState() {
    return HomePageBasicMessageChannelState();
  }

}

class HomePageBasicMessageChannelState extends State<HomePageBasicMessageChannel>
{
  static const BasicMessageChannel<String> platform = BasicMessageChannel<String>('samples.flutter.io/basic', StringCodec()); String result; String result2; Future<String> _handlePlatformIncrement(String message) Async {// Here to receive messages sent by AndroidsetState(() { result=message; }); // This is passed back to Android, which can receive itreturn "Flutter got a message. This is a message back to you.";
  }


  @override
  Widget build(BuildContext context) {
    platform.setMessageHandler(_handlePlatformIncrement);
    return Scaffold(

      body: Center(
        child: Column(
          children: <Widget>[
            Text("Received the message from Android:${result}"),
            InkWell(
              child: Text("Send message"), onTap: (){// here is the code that sends the active message to Android platform.send("Messages actively sent by flutter");
              },
            ),
            Text("Android returns a message from flutter:${result2}"() [(), (), (); }}Copy the code

Use the EventChannel

This feels more like the application of observer mode. When the event that the flutter wants to listen for changes (such as network changes, battery changes), Android will actively send events to the flutter. For example, the flutter wants to know the battery changes in real time. If you use EventChannel, you don’t need to poll

Core code:

The Android side:

new EventChannel(flutterView, "samples.flutter.io/charging").setStreamHandler(
                new EventChannel.StreamHandler() {// BroadcastReceiver to receive battery broadcasts. private BroadcastReceiver chargingStateChangeReceiver; Override // This onListen is the callback when the Flutter end starts to listen on this channel. The second EventSink parameter is the carrier used to transmit data. public void onListen(Object arguments, EventChannel.EventSink events) { globaleEvents=events; chargingStateChangeReceiver = createChargingStateChangeReceiver(events); registerReceiver( chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); } @ Override public void onCancel (Object the arguments) {/ / no longer receives the opposite unregisterReceiver (chargingStateChangeReceiver); chargingStateChangeReceiver = null; }}); tv2.setOnClickListener(new View.OnClickListener(){@override public void onClick(View v)if(globaleEvents! =null) { globaleEvents.success("The charge has changed."+ new Random().nextInt(20)); }}});Copy the code
/** * param events * @param eventsreturn
     */
    private BroadcastReceiver createChargingStateChangeReceiver(final EventChannel.EventSink events) {
        return new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);

                if (status == BatteryManager.BATTERY_STATUS_UNKNOWN) {
                    events.error("UNAVAILABLE"."Charging status unavailable", null);
                } else{ boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;  // Send the status of the Flutter to the events.success(isCharging?"charging" : "discharging"); }}}; }Copy the code

The flutter end:

class HomePageEventState extends State<HomePageEvent>
{
  static const EventChannel eventChannel = const EventChannel('samples.flutter.io/charging');

  String _chargingStatus;
  @override
  void initState() { super.initState(); eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError); } void _onEvent(Object event) {setState(() {
//      _chargingStatus =
//      "Battery status: ${event == 'charging' ? '' : 'dis'}charging.";
    _chargingStatus=event.toString();
    });
  }

  void _onError(Object error) {
    setState(() {
      _chargingStatus = 'Battery status: unknown.';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("${_chargingStatus}"),),); }}Copy the code

MethodChannel

Methodchannels are more like methods used to call each other. When Android calls a flutter method, it can pass in parameters. When a flutter calls an Android method, it doesn’t find a place to pass parameters

Core code: Android terminal

final MethodChannel channel=new MethodChannel(flutterView, CHANNEL);
        channel.setMethodCallHandler(
                new MethodChannel.MethodCallHandler() {@override public void onMethodCall(MethodCall call, methodchannel.result Result) {// Handle calls from Flutter in this callbackif (call.method.equals("getBatteryLevel")) {
                            int batteryLevel = getBatteryLevel();

                            if(batteryLevel ! = -1) { result.success(batteryLevel); }else {
                                result.error("UNAVAILABLE"."Battery level not available.", null); }}else{ result.notImplemented(); }}}); tv.setOnClickListener(new View.OnClickListener(){@override public void onClick(View v) {@override public void onClick(View v) {"getName"."abc",new MethodChannel.Result(){

                    @Override
                    public void success(Object o) {

                        Toast.makeText(MainActivity.this,o.toString(),Toast.LENGTH_LONG).show();
                    }

                    @Override
                    public void error(String s, String s1, Object o) {

                    }

                    @Override
                    public void notImplemented() {}}); }});Copy the code
private int getBatteryLevel() {
        int batteryLevel = -1;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
            batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        } else {
            Intent intent = new ContextWrapper(getApplicationContext()).
                    registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
            batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
                    intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        }

        return batteryLevel;
    }
Copy the code

The flutter end:

class _MyHomePageState extends State<HomePage>
{
  MethodChannel  platform = const MethodChannel('samples.flutter.io/battery');
  
  String _batteryLevel = 'Unknown battery level.';

  Future<Null> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    setState(() { _batteryLevel = batteryLevel; }); } Future<dynamic> platformCallHandler(MethodCall call) async {//call.method Call.arguments gets method arguments switch (call.method) {case "getName":
        return "Hello from Flutter:${call.arguments}";
        break; }} @override Widget build(BuildContext context) {// To enable native methods to be called in a flutter platform.setMethodCallHandler(platformCallHandler); // TODO: implement buildreturn Scaffold(
      body: Center(
        child:Column(
          children: <Widget>[
            Text("Battery:${_batteryLevel}"),

            IconButton(
                icon: Icon(Icons.ac_unit), onPressed: (){
              _getBatteryLevel();
            },
              tooltip: "Get power"() [(), (), (). }}Copy the code