1. 程式人生 > 其它 >Flutter混合開發Android篇

Flutter混合開發Android篇

Flutter混合開發IOS篇

在Mac上搭建Flutter開發環境

1.下載Flutter SDK ((Channel stable, v1.17.1, on Mac OS X 10.15.7 19H15, locale zh-Hans-CN),不要下載最新的SDK,相容混合開發框架 flutter_boost: ^1.17.1。

2.下載四個外掛,分別為 Flutter、Dart、FishReduxTemplate、Flutter Intl。流程圖如下:
Preferences | Plugins

3.檢查三個SDK的配置,分別為Androd SDK、Flutter SDK、
Dart SDK. 流程圖如下:
Preferences | Appearance & Behavior | System Settings | Android SDK
Preferences | Languages & Frameworks | Flutter
Preferences | Languages & Frameworks | Dart

Mac上搭建Flutter開發環境

IOS Flutter混合開發

建立module

1.在IOS專案的同級目錄新建Flutter Module

File | New | New Flutter Project… | Flutter Module

2.Flutter module專案整合FlutterBoost

在flutter_module專案的pubspec.yaml檔案中新增依賴外掛配置

dependencies:
  flutter_boost: ^1.17.1

配置完成後執行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整合日誌

IOS原生專案中整合FlutterBoost

1. 修改 Podfile 檔案

flutter_application_path = '../flutter_module/'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'YiHome2.0' do
  install_all_flutter_pods(flutter_application_path)

2.執行命令

pod install

3.新增 PlatformRouterImp.h

//
//  PlatformRouterImp.h
//  YiHome2.0
//
//  Created by liubing on 2020/11/26.
//  Copyright © 2020 xiaoyi. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <flutter_boost/FlutterBoost.h>

NS_ASSUME_NONNULL_BEGIN

@protocol FLBPlatform;

/**
 * 實現平臺側的頁面開啟和關閉,不建議直接使用用於頁面開啟,建議使用FlutterBoostPlugin中的open和close方法來開啟或關閉頁面;
 * FlutterBoostPlugin帶有頁面返回資料的能力
 */
@interface PlatformRouterImp : NSObject<FLBPlatform>
@property (nonatomic,strong) UINavigationController *navigationController;
@end

NS_ASSUME_NONNULL_END

4.新增 PlatformRouterImp.m

//
//  PlatformRouterImp.m
//  YiHome2.0
//
//  Created by liubing on 2020/11/26.
//  Copyright © 2020 xiaoyi. All rights reserved.
//

#import "PlatformRouterImp.h"
#import <flutter_boost/FlutterBoost.h>
#import "JJDeviceShareQRCodeScanSuccessViewController.h"

@interface PlatformRouterImp()
- (UINavigationController *)currentNC;
@end

@implementation PlatformRouterImp

#pragma mark - Boost 1.5
- (void)open:(NSString *)name
   urlParams:(NSDictionary *)params
        exts:(NSDictionary *)exts
  completion:(void (^)(BOOL))completion
{
    if ([name isEqualToString:@"yicamera://DeviceShareResultActivity"]) {
//        KeyConst.DEVICE_SHARE_WAY: KeyConst.DEVICE_SHARE_WAY_ACCOUNT,
//        KeyConst.DEVICE_SHARE_MESSAGE_ID: infoInvitee.id,
//        KeyConst.DEVICE_SHARE_TOKEN: infoInvitee.shareToken,
//        KeyConst.DEVICE_SHARE_OWNER_NAME: infoInvitee.nickName,
        JJDeviceShareQRCodeScanSuccessViewController * vc = DYY_Create_Alloc(JJDeviceShareQRCodeScanSuccessViewController);
        vc.stringInvitedUserId = params[@"DEVICE_SHARE_OWNER_NAME"];
        vc.stringShareToken = params[@"DEVICE_SHARE_TOKEN"];
        int type = 2;
        vc.shareType = type == 2 ? JJShareTypeAccount : JJShareTypeQRCode;
        [[self currentNC] pushViewController:vc animated:YES];
        // TODO 裝置邀請
        return;
    }
    
    BOOL animated = [exts[@"animated"] boolValue];
    FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
    [vc setName:name params:params];
    [[self currentNC] pushViewController:vc animated:animated];
    if(completion) completion(YES);
}

- (void)present:(NSString *)name
   urlParams:(NSDictionary *)params
        exts:(NSDictionary *)exts
  completion:(void (^)(BOOL))completion
{
    BOOL animated = [exts[@"animated"] boolValue];
    FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
    [vc setName:name params:params];
    [[self currentNC] presentViewController:vc animated:animated completion:^{
        if(completion) completion(YES);
    }];
}

- (void)close:(NSString *)uid
       result:(NSDictionary *)result
         exts:(NSDictionary *)exts
   completion:(void (^)(BOOL))completion
{
    BOOL animated = [exts[@"animated"] boolValue];
    animated = YES;
    FLBFlutterViewContainer *vc = (id)[self currentNC].presentedViewController;
    if([vc isKindOfClass:FLBFlutterViewContainer.class] && [vc.uniqueIDString isEqual: uid]){
        [vc dismissViewControllerAnimated:animated completion:^{}];
    }else{
        [[self currentNC] popViewControllerAnimated:animated];
    }
}



- (UINavigationController *)currentNC
{
    if (![[UIApplication sharedApplication].windows.lastObject isKindOfClass:[UIWindow class]]) {
        NSAssert(0, @"未獲取到導航控制器");
        return nil;
    }
    UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    return [self getCurrentNCFrom:rootViewController];
}

//遞迴
- (UINavigationController *)getCurrentNCFrom:(UIViewController *)vc
{
    if ([vc isKindOfClass:[UITabBarController class]]) {
        UINavigationController *nc = ((UITabBarController *)vc).selectedViewController;
        return [self getCurrentNCFrom:nc];
    }
    else if ([vc isKindOfClass:[UINavigationController class]]) {
        if (((UINavigationController *)vc).presentedViewController) {
            return [self getCurrentNCFrom:((UINavigationController *)vc).presentedViewController];
        }
        return [self getCurrentNCFrom:((UINavigationController *)vc).topViewController];
    }
    else if ([vc isKindOfClass:[UIViewController class]]) {
        if (vc.presentedViewController) {
            return [self getCurrentNCFrom:vc.presentedViewController];
        }
        else {
            return vc.navigationController;
        }
    }
    else {
        NSAssert(0, @"未獲取到導航控制器");
        return nil;
    }
}

@end

5.修改 AppDelegate.h

#import <flutter_boost/FlutterBoost.h>

6.修改 AppDelegate.m

#import "AppDelegate.h"
#import "PlatformRouterImp.h"
#import <flutter_boost/FlutterBoost.h>
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 ...
router = [PlatformRouterImp new];
    [FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
    onStart:^(FlutterEngine *engine) {
        // 註冊MethodChannel,監聽flutter側的getPlatformVersion呼叫
        FlutterMethodChannel *flutterMethodChannel = [FlutterMethodChannel methodChannelWithName:@"flutter_native_channel" binaryMessenger:engine.binaryMessenger];
                
        [flutterMethodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
                    
        NSString *method = call.method;
            if ([@"getUser" isEqualToString:call.method]) {
                dispatch_async(dispatch_get_global_queue(0, 0), ^{
                    NSError *error = nil;
                    [JJSingleAccount sharedJJSingleAccount];
                    JJSingleAccount *account = [JJSingleAccount sharedJJSingleAccount];
                    NSString *user = [account mj_JSONString];
                    NSDictionary *r = @{@"user":user};
                    NSData *data = [NSJSONSerialization dataWithJSONObject:r options:NSJSONWritingPrettyPrinted error:&error];
                    result(data);
                });
            } else if ([method isEqualToString:@"getPlatformVersion"]) {
                NSString *sysVersion = [[UIDevice currentDevice] systemVersion];
                result(sysVersion);
            } else {
                result(FlutterMethodNotImplemented);
            }
                    
        }];
    }];
    
	return YES;
}

7. 開啟Flutter介面

[FlutterBoostPlugin open:@"notification" urlParams:nil exts:@{@"animated":@(YES)}onPageFinished:^(NSDictionary *result) {
                NSLog(@"call me when page finished, and your result is:%@", result);
            } completion:^(BOOL f) {
                NSLog(@"page is opened");
            }];

學習資料

Flutter官網
Dart官網
依賴包
OpenFlutter社群
flutter_boost 混合開發框架
fish_redux架構開發