APP开发平台 > Blog > Flutter混合开发Android APP

Flutter混合开发Android app技巧


在Windows上搭建Flutter开发环境


1.下载Flutter SDK (Channel stable, v1.17.1, on Microsoft Windows [Version 10.0.18363.1256], locale zh-CN),不要下载最新的SDK,兼容混合开发框架 flutter_boost: ^1.17.1。


2.下载四个插件,分别为 Flutter、Dart、FishReduxTemplate、Flutter Intl。流程图如下:

File | Settings | Plugins


3.检查三个SDK的配置,分别为Androd SDK、Flutter SDK、

Dart SDK. 流程图如下:

File | Settings | Appearance & Behavior | System Settings | Android SDK

File | Settings | Languages & Frameworks | Flutter

File | Settings | Languages & Frameworks | Dart


Windows上搭建Flutter开发环境


Android Flutter混合开发

创建module

1.在Android项目的同级目录新建Flutter Module

File | New | New Flutter Project… | Flutter Module


2.Flutter module项目集成FlutterBoost

在flutter_module项目的pubspec.yaml文件中添加依赖插件配置


dependencies:

  flutter_boost: ^1.17.1

1

2

配置完成后执行flutter packages get命令下载依赖插件到本地


需要了解 pub get 和 pub upgrade 命令 , 打开pubspec.yaml这两个命令就能显示出来


pub get

在项目中配置了pubspec文件后,就可以在项目根目录中执行pub get命令


pub upgrade

第一次获取依赖时,Pub 会下载依赖及其兼容的最新版本。然后通过创建lockfile 锁定依赖,以始终使用这个版本。 Pub会在pubspec旁创建并存储一个名为pubspec.lock文件。它列出了使用的每个依赖包的指定版本(当前包或传递包的版本)。


3.运行代码

1.直接点击绿色的箭头Run就能独立运行到手机里面。

2.Build | Flutter | Build AAR ,就能编译出AAR文件,并生成Android集成日志


安卓原生项目中集成FlutterBoost

1.将文件夹的名改为app

将文件夹的名改为app, 否则会报错。


2.修改 settings.gradle 文件

include ':app', ':MiHomeSDK'

setBinding(new Binding([gradle: this]))

evaluate(new File(

        settingsDir.parentFile,

        'flutter_module/.android/include_flutter.groovy'

))

include ':flutter_module'

project(':flutter_module').projectDir = new File('../flutter_module')


3.修改最外层目录下的build.gradle 文件

1.增加 maven {url ‘http://download.flutter.io’}


buildscript {

   ...

    repositories {

        ...

        maven {url 'http://download.flutter.io'}

    }

    dependencies {

        ...

    }

}


allprojects {

    repositories {

        ...

        maven {url 'http://download.flutter.io'}

    }

}


4.修改app目录下的build.gradle 文件

repositories {

    maven {url '../../flutter_module/build/host/outputs/repo'}

}


debugImplementation 'com.xiaoyi.flutter_module:flutter_debug:1.0'

    profileImplementation 'com.xiaoyi.flutter_module:flutter_profile:1.0'

    releaseImplementation 'com.xiaoyi.flutter_module:flutter_release:1.0'


5.修改app目录下的AndroidManifest.xml文件

<activity

            android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"

            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"

            android:hardwareAccelerated="true"

            android:windowSoftInputMode="adjustResize" >

       </activity>


6. 增加Flutter文件

里面包含三个Java 文件, 是自己封装,主要是初始化、通道、路由等功能

FlutterUtil.java


package com.ants360.yicamera.flutter;


import android.app.Application;

import android.os.Build;


import com.ants360.yicamera.base.UserManager;

import com.ants360.yicamera.bean.User;

import com.google.gson.Gson;

import com.idlefish.flutterboost.FlutterBoost;

import com.idlefish.flutterboost.Platform;

import com.idlefish.flutterboost.Utils;

import com.idlefish.flutterboost.interfaces.INativeRouter;


import java.util.HashMap;

import java.util.Map;


import io.flutter.embedding.android.FlutterView;

import io.flutter.plugin.common.EventChannel;

import io.flutter.plugin.common.MethodChannel;

import io.flutter.plugin.common.StandardMessageCodec;


public class FlutterUtil {

    public static void init(Application app) {

        INativeRouter router = (context, url, urlParams, requestCode, exts) -> {

            String assembleUrl = Utils.assembleUrl(url, urlParams);

            PageRouter.openPageByUrl(context, assembleUrl, urlParams);

        };


        FlutterBoost.BoostLifecycleListener boostLifecycleListener = new FlutterBoost.BoostLifecycleListener() {


            @Override

            public void beforeCreateEngine() {


            }


            @Override

            public void onEngineCreated() {


                // 注册MethodChannel,监听flutter侧的getPlatformVersion调用

                MethodChannel methodChannel = new MethodChannel(FlutterBoost.instance().engineProvider().getDartExecutor(), "flutter_native_channel");

                methodChannel.setMethodCallHandler((call, result) -> {

                    if (call.method.equals("getPlatformVersion")) {

                        result.success(Build.VERSION.RELEASE);

                    } else if (call.method.equals("getUser")) {

                        User user  = UserManager.getInstance().getUser();

                        Map<String, String> map = new HashMap<>();

                        Gson gson = new Gson();

                        map.put("user", gson.toJson(user));

                        result.success(map);

                    }else {

                        result.notImplemented();

                    }


                });



                EventChannel methodChannel2 = new EventChannel(FlutterBoost.instance().engineProvider().getDartExecutor(), "native_flutter_channel");

                methodChannel2.setStreamHandler(new EventChannel.StreamHandler() {

                    @Override

                    public void onListen(Object arguments, EventChannel.EventSink events) {

                        events.success("msg");

                    }


                    @Override

                    public void onCancel(Object arguments) {

                    }

                });


                // 注册PlatformView viewTypeId要和flutter中的viewType对应

                FlutterBoost

                        .instance()

                        .engineProvider()

                        .getPlatformViewsController()

                        .getRegistry()

                        .registerViewFactory("plugins.test/view", new TextPlatformViewFactory(StandardMessageCodec.INSTANCE));


            }


            @Override

            public void onPluginsRegistered() {


            }


            @Override

            public void onEngineDestroy() {


            }


        };


        Platform platform = new FlutterBoost

                .ConfigBuilder(app, router)

                .isDebug(true)

                .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)

                .renderMode(FlutterView.RenderMode.texture)

                .lifecycleListener(boostLifecycleListener)

                .build();

        FlutterBoost.instance().init(platform);

    }

}



PageRouter.java


package com.ants360.yicamera.flutter;


import android.app.Activity;

import android.content.Context;

import android.content.Intent;

import android.util.Log;


import com.ants360.yicamera.activity.camera.share.DeviceShareResultActivity;

import com.ants360.yicamera.constants.KeyConst;

import com.idlefish.flutterboost.containers.BoostFlutterActivity;


import java.util.HashMap;

import java.util.Map;


public class PageRouter {


    public final static Map<String, String> pageName = new HashMap<String, String>() {{


        put("notification", "notification");

        put("device_login_message", "device_login_message");

        put("device_Share_message", "device_Share_message");



        put("first", "first");

        put("second", "second");

        put("tab", "tab");

        put("sample://flutterPage", "flutterPage");

    }};


    public static final String NATIVE_PAGE_URL_DEVICE_SHARE_RESULT_ACTIVITY = "yicamera://DeviceShareResultActivity";



    public static final String NATIVE_PAGE_URL = "sample://nativePage";

    public static final String FLUTTER_PAGE_URL = "sample://flutterPage";

    public static final String FLUTTER_FRAGMENT_PAGE_URL = "sample://flutterFragmentPage";


    public static boolean openPageByUrl(Context context, String url, Map params) {

        return openPageByUrl(context, url, params, 0);

    }


    public static boolean openPageByUrl(Context context, String url, Map params, int requestCode) {


        String path = url.split("\\?")[0];


        Log.i("openPageByUrl",path);


        try {

            if (pageName.containsKey(path)) {

                Intent intent = BoostFlutterActivity.withNewEngine().url(pageName.get(path)).params(params)

                        .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque).build(context);

                if(context instanceof Activity){

                    Activity activity = (Activity) context;

                    activity.startActivityForResult(intent,requestCode);

                }else{

                    context.startActivity(intent);

                }

                return true;

            } else if (url.startsWith(NATIVE_PAGE_URL_DEVICE_SHARE_RESULT_ACTIVITY)) {

                Intent intent = new Intent(context, DeviceShareResultActivity.class);

                if( null != params) {

                    intent.putExtra(KeyConst.DEVICE_SHARE_WAY, params.get(KeyConst.DEVICE_SHARE_WAY).toString());

                    intent.putExtra(KeyConst.DEVICE_SHARE_MESSAGE_ID, params.get(KeyConst.DEVICE_SHARE_MESSAGE_ID).toString());

                    intent.putExtra(KeyConst.DEVICE_SHARE_TOKEN, params.get(KeyConst.DEVICE_SHARE_TOKEN).toString());

                    intent.putExtra(KeyConst.DEVICE_SHARE_OWNER_NAME, params.get(KeyConst.DEVICE_SHARE_OWNER_NAME).toString());

                }

                if(context instanceof Activity){

                    Activity activity = (Activity) context;

                    activity.startActivityForResult(intent, requestCode);

                }else{

                    context.startActivity(intent);

                }

                return true;

            } else if (url.startsWith(FLUTTER_FRAGMENT_PAGE_URL)) {

//                context.startActivity(new Intent(context, FlutterFragmentPageActivity.class));

                // TODO

                return true;

            } else if (url.startsWith(NATIVE_PAGE_URL)) {

//                context.startActivity(new Intent(context, NativePageActivity.class));

                // TODO

                return true;

            }


            return false;


        } catch (Throwable t) {

            return false;

        }

    }

}


TextPlatformViewFactory.java


package com.ants360.yicamera.flutter;


import android.content.Context;

import android.view.View;

import android.widget.TextView;


import io.flutter.plugin.common.MessageCodec;

import io.flutter.plugin.platform.PlatformView;

import io.flutter.plugin.platform.PlatformViewFactory;


public class TextPlatformViewFactory extends PlatformViewFactory {


    public TextPlatformViewFactory(MessageCodec<Object> createArgsCodec) {

        super(createArgsCodec);

    }


    @Override

    public PlatformView create(Context context, int i, Object o) {

        return new TextPlatformView(context);

    }


    private static class TextPlatformView implements PlatformView {


        private TextView platformTv;


        public TextPlatformView(Context context) {

            platformTv = new TextView(context);

            platformTv.setText("PlatformView Demo");

        }


        @Override

        public View getView() {

            return platformTv;

        }


        @Override

        public void dispose() {


        }

    }

}


7. Application 初始化

@Override

    public void onCreate() {

        super.onCreate();

        FlutterUtil.init(this);

   }


8. 打开Flutter界面

PageRouter.openPageByUrl(getActivity(), PageRouter.pageName.get("notification") , null);


9.混淆

@Keep

public class User implements IUser {

}


————————————————

版权声明:本文为CSDN博主「weixin_38951817」的原创文章

原文链接:https://blog.csdn.net/weixin_38951817/article/details/111151950


来APICloud移动应用开发平台学习更多免费APP开发知识:app开发 app开发源码下载 app开发视频教程 app制作模板等免费获取。APICloud支持一键网站自动生成app网站转app网站封装app,有网站即可生成自己的app。

 

立即免费在线制作一个APP,新手注册即送开发大礼包

 

提交app定制需求,了解报价和周期:

 

电脑请点击https://app.apicloud.com/index?uzchannel=500

手机请点击https://app.apicloud.com/m/quickaddcustom


An efficient app outsourcing platform that guarantees timely delivery!

Submit Requirements