WADE移動應用框架幫助文檔

整個移動應用框架是採用Hybrid模式構建,分爲H5端和原生端。就目前適應CRM複雜又經常變動的業務,我們以H5爲主,原生爲輔的形式構建我們的app。H5端採用原生控件webview承接,原生端對應的平臺各自研發承接。既然是由兩部分構成,就需要一種框架能支持兩者之間的交互。仔細研究Android和iOS這兩個平臺的webview控件的源碼和內核,它們都支持一種叫”語言穿梭機”的機制:Android可從Java對象穿梭到JS中構造成JS對象,反之亦然;iOS可從OC對象穿梭到JS中構成JS對象,反之也亦然。只是在Android端是系統類支持的,而iOS端需要從webview內核中遍歷出這個穿梭機的上下文對象,在這個穿梭機的上下文對象中註冊Java對象,進而穿梭到H5中變成JS對象;

一、H5端接入步驟

1、爲兼容PC需引入plugin.js

此js對原生插件API做一個PC端的API的映射,目前我們給一個基礎的插件API樣例JS,可根據項目的需要增加插件接口,plugin.js內容如下:


$(document).ready(function(){

    mboss.noTerminal = {
        error: function(){
            alert('請在手機終端運行此方法');
            return false;
        },
        returnEmptyStr: function(){
            return '';
        }, 
    };
    /* 框架相關方法兼容 */
    if (!window.ExtendScriptPlugin){
        window.ExtendScriptPlugin = {};
        ExtendScriptPlugin.JN_Photograph = mboss.noTerminal.error;//拍照

        /* 本地存儲 */
        //localStorage操作
        mboss.storage = {
            get: function(name){
                return window.localStorage.getItem(name) || '';
            },
            set: function(name, value){
                window.localStorage.setItem(name, value);
            },
            remove: function(name){
                window.localStorage.removeItem(name); 
            },
            clear:function(){
                window.localStorage.clear();
            }
        };

        ExtendScriptPlugin.JN_GetValueWithKey = mboss.storage.get;
        ExtendScriptPlugin.JN_SetValueWithKey = mboss.storage.set;
        ExtendScriptPlugin.JN_RemoveAllData = mboss.storage.clear;
        ExtendScriptPlugin.JN_RemoveDataByKey = mboss.storage.remove;
    }
});

(1)第14行的ExtendScriptPlugin就是原生插件對象;
(2)以JN_開頭的API就是插件的原生API, 在plugin.js中我們做一個PC端API的映射,例如,JN_Photograph 在PC端就映射成mboss.noTerminal.error。如果應用運行在手機端,就會調用原生API:JN_Photograph。
(3)第35-38是做數據存儲的函數的映射

2、在H5頁面中調用原生接口

假定原生定義的JN_Photograph如下:

- (void)JN_Photograph:(NSString*)functionName;

1)非iframe頁面中使用

請使用window對象引用插件對象:

window.ExtendScriptPlugin.JN_Photograph('callbackFunctionName');

2)在iframe頁面中使用

請使用top對象引用插件對象:

top.ExtendScriptPlugin.JN_Photograph('callbackFunctionName');

3、js回調函數的處理

目前我們是採用給原生接口傳入回調函數名的方式實現JS回調,如上面的JN_Photograph。後面我們會支持JS匿名函數的回調方式。

二、原生端接入步驟

1、iOS平臺接入步驟

1)引入AIBase.framework框架包

2)定義插件接口穿梭協議

此協議繼承自系統的穿梭協議JSExport。 在協議中定義插件提供給H5端調用的原生API,如圖所示我們定義的插件基類的穿梭協議:

/**
 *  擴展插件類
 *  1、JSExport是JS與OC之間的穿梭機;
 *  2、把需要擴展的API定義到protocol:JSExport裏,在插件類裏實現接口;
 *  3、若是多參數的API,可以採用JSExportAs來聲明接口,可以參考ScriptPluginBase;默認的情況,在JS端是會把參數tag首字母大寫拼接成JS的function調用方式,例如:test:(NString*)str key:(NString*)k --> testKey(str,k);
 *  4、注意,擴展的API,如果要操作UI的,一定要在主線程裏調用。很多情況,jscontext是非主線程調用API;
 */

@protocol JN_BasePluginExport <JSExport>

// 基礎的能力接口
// 1、數據存取
JSExportAs(JN_SetValueWithKey,- (void)JN_SetValueWithKey:(NSString*)key value:(NSString*)value);
- (NSString*)JN_GetValueWithKey:(NSString*)key;
- (void)JN_RemoveAllData;
- (void)JN_RemoveDataByKey:(NSString*)key;

// 2、數據安全
- (NSString*)JN_Encrypt:(NSString*)context;
- (NSString*)JN_Decrypt:(NSString*)encrypt;
- (NSString*)JN_IDMD5:(NSString*)userName;
- (NSString*)JN_Token:(NSString*)params;
JSExportAs(JN_ShowFadeMsg, -(void)JN_ShowFadeMsg:(NSString *)msg status:(int)status);

// 隱藏鍵盤
- (void)JN_HideKeyboard;
// 獲取手機型號等信息
- (NSString *)JN_GetPhoneModule;
@end

由於OC與JS定義函數的語法不同,針對有多個入參的函數,應該採用JSExportAs做函數語法的映射,如上圖的 JN_SetValueWithKey,它在JS中的定義爲:

function JN_SetValueWithKey(key,value); 

在OC中定義爲:

- (void)JN_SetValueWithKey:(NSString*)key value:(NSString*)value;

爲了後面的講述,我們假設插件定義的穿梭協議:

@protocol JN_ExtendPluginExport <JSExport>
@end

3)繼承插件的基類:AIWebViewBasePlugin

假設子類的類名爲:ExtendScriptPlugin

4)實現穿梭協議

插件類需要實現穿梭協議定義的API:

@interface ExtendScriptPlugin : AIWebViewBasePlugin<JN_ExtendPluginExport>
@end

請在ExtendScriptPlugin中實現JN_ExtendPluginExport中定義的函數。注意:在實現穿梭協議的函數的時候,如果該函數有操作UI,包括H5和原生的UI元素的操作,請在UI主線程中執行這些代碼 如下面的代碼所示:

- (void)JN_Photograph:(NSString*)functionName {
    __weak CRMMainVC *vc = (CRMMainVC*)self.vc;
    dispatch_async(dispatch_get_main_queue(), ^{
        [vc JN_Photograph:functionName];
    });
}

上面dispatch_async就是iOS平臺推薦的主線程中執行代碼的標準寫法,這樣[vc JN_Photograph:functionName]就會在UI主線程中執行。

5)配置H5插件

爲了配置文件通用性,我們iOS和android採用同一種xml格式的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<plugins>
    <plugin name="ExtendScriptPlugin" class="com.ai.crmapp.ExtendScriptPlugin" packageName="com.ai.crmapp"></plugin>
</plugins>

配置中我們可以配置多個plugin。這裏僅配置一個,即上面定義的ExtendScriptPlugin。對於iOS平臺class和packageName兩個字段是無效的。假定我們的配置文件爲:h5Plugin.xml。

6)向WebView內核中註冊H5插件

在我們框架中提供插件引擎類:AIWebViewPluginEngine。它目前主要兩個能力:一、註冊上述配置的H5插件;二、調用H5的JS 函數;

(1)註冊H5插件

- (void)registerH5Engine:(UIWebView*)webView {
    NSData *configData = [[AIPluginTools SharedObj] roadResWithName:@"h5Plugin.xml"];
    AIWebViewPluginEngine *engine = [AIWebViewPluginEngine SharedObj];
    [engine registerPluginsInVC:self webView:webView configData:configData];
}

上述代碼讀取插件配置文件h5Plugin.xml,然後通過通過插件引擎在webview上註冊插件。

(2)通過引擎調用H5的JS

我們的回調JS函數以及原生需要調用H5的JS函數都可通過引擎調用H5的JS

dispatch_async(dispatch_get_main_queue(), ^{
                NSString *js = [NSString stringWithFormat:@"%@('%@')",@"JS_SetScanResult",result];
                AIWebViewPluginEngine *engine = [AIWebViewPluginEngine SharedObj];
                [engine excuteJavascript:js];
            });

上述對象js即我們需要調用H5中的JS。這裏我們也採用在主線程中執行調用(因爲這個執行的JS會操作H5的圖片展示控件)

2、android平臺接入步驟

1)引入框架jar包

請在android studio中引入我們的框架包 aibase.jar和wade-data.jar。

2)繼承插件的基類:AIWebViewBasePlugin

假設子類的類名爲,ExtendScriptPlugin:

/**
 * Created by wuyoujian on 2017/5/4.
 */

public class ExtendScriptPlugin extends AIWebViewBasePlugin {

3)定義H5調用的原生接口

在Android平臺定義一個H5調用的原生接口只需要做的兩點:一、是public的函數;二、需要增加註解:@JavascriptInterface。如下面的一個插件函數:

// 拍照
    @JavascriptInterface
    @NotProguard
    public void JN_Photograph(String functionName) {
        final String  mFunctionName = functionName;
        final String checkPermissinos [] = {Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE};
        PermissionUitls.mContext = getActivity();
        if(!PermissionUitls.isGetAllPermissionsByList(checkPermissinos) ) {
            new AlertDialog
                    .Builder(getActivity())
                    .setTitle("提示信息")
                    .setMessage("該功能需要您接受應用對一些關鍵權限(拍照)的申請,如之前拒絕過,可到手機系統的應用管理授權設置界面再次設置。")
                    .setPositiveButton("確認", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            checkPermission(mFunctionName,PermissionUitls.PERMISSION_CAMERA_CODE,checkPermissinos);
                        }
                    }).show();
        } else {

            jumpToRectCameraActivity(functionName);
        }
    }

4)配置H5插件

爲了配置文件通用性,我們iOS和android採用同一種xml格式的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<plugins>
    <plugin name="ExtendScriptPlugin" class="com.ai.crmapp.ExtendScriptPlugin" packageName="com.ai.crmapp"></plugin>
</plugins>

配置中我們可以配置多個plugin。這裏僅配置一個,即上面定義的ExtendScriptPlugin。對於iOS平臺class和packageName兩個字段是無效的。假定我們的配置文件爲:h5Plugin.xml。

5)向WebView內核中註冊H5插件

在我們框架中提供插件引擎類:AIWebViewPluginEngine。它目前主要兩個能力:一、註冊上述配置的H5插件;二、調用H5的JS 函數;

(1)註冊H5插件

private void setH5PluginEngine() {
        AIWebViewPluginEngine_dl engine = AIWebViewPluginEngine_dl.getInstance();
        engine.registerPlugins(this, mWebView, mPluginCfgFile);
    }

mWebView是webview控件,mPluginCfgFile 就是上述定義的插件配置文件: h5Plugin.xml,這個配置文件請放在assets裏,如圖所示:
這裏寫圖片描述

(2)通過引擎調用H5的JS

我們的回調JS函數以及原生需要調用H5的JS函數都可通過引擎調用H5的JS。

runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            AIWebViewPluginEngine_dl engine = AIWebViewPluginEngine_dl.getInstance();
                            String JS = String.format("%s('%s','%s')","JS_LaunchApp_callback","0","");
                            engine.excuteJavascript(JS, new ValueCallback<String>() {
                                @Override
                                public void onReceiveValue(String value) {
                                    LogUtil.d("jsMethod",value);
                                }
                            });
                        }
                    });

同理,在插件函數裏如果會牽涉到操作UI元素(包括原生和H5)都需要在UI主線程中執行,如上面的runOnUiThread

三、框架提供的能力

目前iOS平臺提供比較全面支撐crm的能力,android目前提供的部分能力,後面會根據iOS平臺以及業務的需求兩個平臺能力做的一致。

1、iOS平臺提供的能力

1)自定義證件拍照控件類AICaptureView

範例:

//243px x 153px
    CGFloat width = 200 * 243 / 153;
    CGRect markFrame = CGRectMake((self.view.frame.size.width - width)/2.0, 184, width, 200);
    AICaptureView *captureView = [[AICaptureView alloc] initWithFrame:self.view.bounds];
    self.captureView = captureView;
    [_captureView cropRectForInterest:markFrame];
    [self.view addSubview:captureView];

上述cropRectForInterest設置證件拍照的區域框。

2)手寫控件類SignatureView

控件中提供了畫筆的基本的操作:筆的大小、筆的顏色、撤銷一筆、重做一筆、清除所有筆畫、保存簽名圖片。
範例:

__weak SignatureViewController *wSelf = self;
    self.signView = [[SignatureView alloc] initWithFrame:CGRectMake(0, [DeviceInfo navigationBarHeight], self.view.frame.size.width, [DeviceInfo screenHeight] - [DeviceInfo navigationBarHeight] - 44) status:^(SigntureStatus status) {
        //
        SignatureViewController *sSelf = wSelf;
        if (status == SignatureStatusBegin) {
            [sSelf.undoItem setEnabled:YES];
        }
    }];

    [_signView setPenSize:3.0];
    [self.view addSubview:_signView];

3)手勢密碼控件類AIGesturePasswordView

範例:

// 創建控件
_passwordView = [[AIGesturePasswordView alloc] initWithFrame:CGRectMake(0, 120, self.view.frame.size.width,  self.view.frame.size.height - 60 - 120)];
    [_passwordView setDelegate:self];
    [_passwordView setDefaultColor:[UIColor blackColor]];
    [_passwordView setPathColor:[UIColor colorWithHex:0x378FC9]];
    [_passwordView setSelectColor:[UIColor colorWithHex:0x378FC9]];
    [_passwordView setWrongColor:[UIColor redColor]];
    [self.view addSubview:_passwordView];

// 實現手勢控件回調
#pragma mark - AIGesturePasswordViewDelegate
// 通過手勢設置密碼
- (void)gesturePasswordView:(AIGesturePasswordView*)sender password:(NSString*)password {
}
// 密碼個數小於4位,無效
- (void)gestureInvalidPasswordView:(AIGesturePasswordView*)sender {

}

4)掃碼控件類QRViewController

範例:

QRViewController *qrController = [[QRViewController alloc] init];
    [picker presentViewController:qrController animated:YES completion:^{
        //
        [qrController startScanQRCodeWithFinish:^(NSString *result, QRCodeScanStatus status) {
            //
            [picker dismissViewControllerAnimated:YES completion:^{}];

            ImagePickerController *sSelf = wSelf;
            if (sSelf.finishBlock) {
                sSelf.finishBlock(ImagePickerTypeScanQRCode,ImagePickerStatusSuccess,result);
            }
        }];
    }];

QRViewController是一個ViewController控制器,所以頁面的啓動可以根據需要用push還是用modal方式,上圖實例中是採用的modal方式;startScanQRCodeWithFinish啓動掃描,通過block的方式回調傳回掃描的結果。

5)二維碼圖片識別和生成

是通過給UIImage做一個類別擴展,方法定義如下:

// 生成二維碼
+ (UIImage *)generateQRCode:(NSString *)code width:(CGFloat)width height:(CGFloat)height;
// 二維碼識別
- (NSArray *)recognitionQRCodeFromImage;

6)驗證碼控件類CaptchaControl

範例:

CaptchaControl *codeCtrl = [[CaptchaControl alloc] initWithFrame:CGRectMake(40, 100, 90, 30) interval:60];
    [codeCtrl setBackgroundColor:[UIColor lightTextColor]];
    [codeCtrl addTarget:self action:@selector(getCode:) forControlEvents:UIControlEventTouchUpInside];
    [codeCtrl setDefaultText:@"驗證碼"];
    [self.view addSubview:codeCtrl];

7)循環輪播控件CycleBannerView

範例:

CycleBannerView *banner = [[CycleBannerView alloc] initWithFrame:view.bounds];
    NSArray *images = @[@"http://pic22.nipic.com/20120717/9774499_115645635000_2.jpg",
                        @"http://pic4.nipic.com/20090919/3372381_123043464790_2.jpg",
                        @"http://www.9doo.net/__demo/jd0024/upload/b1.jpg",
                        @"http://pic.58pic.com/58pic/13/18/50/23K58PIC38v_1024.jpg",
                        @"http://pic2.ooopic.com/10/57/50/93b1OOOPIC4d.jpg"];
    [banner reloadData:images];
    [banner setPageControlPos:PageControlPositionRight];
    [banner autoScroll];
    [view addSubview:banner];

可設置pageControl的位置;也可設置是否是自動輪播,默認不自動輪播。

8)自消失的提示框控件FadePromptView

(1)範例-默認位置彈出

[FadePromptView showPromptStatus:@"當前設置暫時沒有辦法發送郵件" duration:1.0 finishBlock:nil];

(2)範例-指定位置彈出

[FadePromptView showPromptStatus:@"請輸入您的筆記~" duration:0.6 positionY:[DeviceInfo screenHeight]- 300 finishBlock:^{
                //
            }];

上述兩個範例都是可以支持提示框消失後的回調。

9)九宮格控件GridMenuView

self.gridView = [[GridMenuView alloc] initWithFrame:CGRectMake(0, [DeviceInfo navigationBarHeight], [DeviceInfo screenWidth], [DeviceInfo screenHeight] - [DeviceInfo navigationBarHeight])];
    [_gridView setDelegate:self];
    [_gridView setColumnCount:3];
    [_gridView setRowHeight:120];

    [self.view addSubview:_gridView];

    [_gridView appendingMenusData:[self gridData]];

- (NSArray *)gridData {

    GridMenuItem *item1 = [[GridMenuItem alloc] init];
    item1.icon = @"http://ico.58pic.com/iconset01/Doraemon-icons/gif/79802.gif";
    item1.title = @"菜單1";
    item1.iconSize = CGSizeMake(60, 60);
    item1.titleFont = [UIFont systemFontOfSize:14];
    item1.titleColor = [UIColor grayColor];

    GridMenuItem *item2 = [[GridMenuItem alloc] init];
    item2.icon = @"http://ico.58pic.com/iconset02/fast_icon_users/gif/13406.gif";
    item2.title = @"菜單2";
    item2.iconSize = CGSizeMake(60, 60);
    item2.titleFont = [UIFont systemFontOfSize:14];
    item2.titleColor = [UIColor grayColor];

    GridMenuItem *item3 = [[GridMenuItem alloc] init];
    item3.icon = @"http://ico.58pic.com/iconset01/Doraemon-icons/gif/79792.gif";
    item3.title = @"菜單3";
    item3.iconSize = CGSizeMake(60, 60);
    item3.titleFont = [UIFont systemFontOfSize:14];
    item3.titleColor = [UIColor grayColor];


    NSArray *menus = @[item1,item2,item3];
    return menus;
}

此九宮格佈局,如下圖所示:
這裏寫圖片描述

10)icon菜單控件AIActionSheet

範例:

AIActionSheet *sheet = [[AIActionSheet alloc] initInParentView:self.tabBarController.view delegate:self];
        for (int i = 0; i < 7; i ++) {
            AISheetItem * item = [[AISheetItem alloc] init];
            item.icon = @"capture.png";
            item.title = [NSString stringWithFormat:@"測試測-%d",i];
            [sheet addActionItem:item];
        }
        [sheet show];

它所展示的效果如下:
這裏寫圖片描述

11)圖片視頻選擇器類ImagePickerController

這個類集成了圖片的選擇,系統的拍照、系統的錄像、二維碼識別等能力。使用簡單請參考.h裏的接口定義即可

12)郵件和短信發送器類MailSMSController

這個類集成了郵件和短信的發送,使用簡單請參考.h裏的接口定義即可。

13)HTTP通信及數據model一體化封裝

通信引擎類NetworkTask,它封裝了常用的http通信API:文件上傳、GET、POST、PUT、DELETE等等,它需要結合數據model類配套使用。
數據model基類NetResultBase。

範例:

// 1、接口調用
NSDictionary* param =[[NSDictionary alloc] initWithObjectsAndKeys:
                              nameString,@"phone",
                              [pwdString md5EncodeUpper:NO],@"passwd",nil];
        [SVProgressHUD showWithStatus:@"正在登錄..." maskType:SVProgressHUDMaskTypeBlack];
        [[NetworkTask sharedNetworkTask] startPOSTTaskApi:API_Login
                                                 forParam:param
                                                 delegate:self
                                                resultObj:[[LoginResult alloc] init]
                                               customInfo:@"login"];

// 2、回調實現
#pragma mark - NetworkTaskDelegate
-(void)netResultSuccessBack:(NetResultBase *)result forInfo:(id)customInfo {
    [SVProgressHUD dismiss];

    if ([customInfo isEqualToString:@"login"]) {
        AppDelegate *app = [AppDelegate shareMyApplication];
        [app.mainVC switchToHomeVC];

        LoginResult *userInfo = (LoginResult *)result;
        [[SysDataSaver SharedSaver] saveUserInfo:userInfo];
    }
}


-(void)netResultFailBack:(NSString *)errorDesc errorCode:(NSInteger)errorCode forInfo:(id)customInfo {
    [SVProgressHUD dismiss];
    [FadePromptView showPromptStatus:errorDesc duration:1.0 finishBlock:^{
        //
    }];
}

// 實現配套的數據model類
//
//  LoginResult.h
//
//  Created by wuyj on 16/12/14.
//  Copyright © 2016年 Asiainfo. All rights reserved.
//

#import "NetResultBase.h"

@interface LoginResult : NetResultBase<NSCoding>
@property (nonatomic, copy)NSString *nick;
@property (nonatomic, copy)NSString *avatar;
@property (nonatomic, copy)NSString *favorCount;
@property (nonatomic, copy)NSString *noteCount;
@property (nonatomic, copy)NSString *user_id;
@property (nonatomic, copy)NSString *phone;
@property (nonatomic, copy)NSString *mood;
@end

注意對於數據model對象,如果數據字段是Array類型,請使用宏定義定義,如下:

@property(nonatomic,strong,getter=arrayLeibie)NSArray        *BaiduParserArray(leibie,NSString);

上述宏定義:BaiduParserArray,裏面有兩個參數第一參數:leibie是Array字段名稱;NSString是Array的item的類型;當然也可以使用自定義的類,如下:

@property(nonatomic,strong,getter=arrayBook)NSArray        *BaiduParserArray(books,BookItem);

上述Array字段名books,Array的item的類型:BookItem,定義如下:

@interface BookItem : NSObject
@property (nonatomic, copy)NSString *id;
@property (nonatomic, copy)NSString *name;
@property (nonatomic, copy)NSString *pic_big;
@property (nonatomic, copy)NSString *pic_small;
@property (nonatomic, copy)NSString *author;
@property (nonatomic, copy)NSString *range;
@property (nonatomic, copy)NSString *type;
@property (nonatomic, copy)NSString *f_age;
@property (nonatomic, copy)NSString *press;
@property (nonatomic, copy)NSString *isbn;
@property (nonatomic, copy)NSString *recommend;
@property (nonatomic, copy)NSString *link;
@property (nonatomic, copy)NSString *comment;
@property (nonatomic, copy)NSString *status;
@property (nonatomic, copy)NSString *created_date;
@property (nonatomic, copy)NSString *created;
@property (nonatomic, copy)NSString *isOnline;
@property (nonatomic, copy)NSString *isFavor;
@property (nonatomic, copy)NSString *price;

@property (nonatomic, copy)NSString *statement;
@property (nonatomic, copy)NSString *brief;
@property (nonatomic, copy)NSString *introduction;
@property (nonatomic, copy)NSString *pic_intr;
@property (nonatomic, copy)NSString *pic_jj;
@end

13)獨立的分享框架

分享能力我們目前是提供一個獨立的framework,目前集成了3個常用的分享平臺: 微信、QQ、微博;
如果需要使用分享能力,請引入我們框架的AIShare.framework框架包。這個框架中主要實現了3大平臺的分享能力,同時集成了支付能力。
主要提供的類如下圖所示:

這裏寫圖片描述

(1)SharedDataModel,分享的數據類;

(2)SharedManager,分享引擎類;

使用範例:

SharedDataModel *sharedData = [[SharedDataModel alloc] init];
        sharedData.content = @"測試URL分享";
        sharedData.title = @"測試視頻分享";
        sharedData.url = @"http://www.tudou.com/programs/view/_cVM3aAp270/";
        sharedData.dataType = SharedDataTypeText;
        [[SharedManager sharedManager] sharedData:sharedData finish:^(NSInteger statusCode,id resp) {
            //
        }];

14)數據存儲、處理集合

(1)keychain存儲類:AISave2Keychain

(2)剪貼板存儲類:AIPasteboard

(3)基於系統的UserDefault存儲類:SysDataSaver

(4)文件存儲類:FileCache

(5)文件流操作類:FileStreamOperation

(6)圖片處理類別:UIImage+Utility和UIImage+ResizeMagick

(7)顏色處理類別:UIColor+Utility

(8)字符串處理類別:NSString+Utility

(9)數據流處理類別:NSData+Crypto

(10)zip解壓縮:ZipArchiveEx

14)framework動態加載框架

這個框架主要是封裝framework的動態加載和資源從framework的自己的bundle中加載的能力。這封裝主要解決就是iOS平臺實現插件機制。
主要掌握下面兩個類的使用,請參考.h文件即可:

(1)AIPluginLoader類:framework插件加載器。

//
//  AIPluginLoader.h
//  CommonProject
//
//  Created by wuyoujian on 2017/6/19.
//
//

#import <Foundation/Foundation.h>
#import "../Owns/AINavigationController.h"
#import "../Owns/AICommonDef.h"
#import "AIPluginProtocol.h"


typedef NS_ENUM(NSInteger,PluginLoadStatus) {

    PluginLoadStatusNone = 0,
    PluginLoadStatusUnDownload = 1,     // 沒有下載
    PluginLoadStatusDownloading = 2,    // 下載中
    PluginLoadStatusDownloaded = 3,     // 下載完畢
    PluginLoadStatusException = 4,      // 加載異常

};

@interface AIPluginLoader : NSObject

AISINGLETON_DEF(AIPluginLoader,SharedObj);

// 獲取插件的狀態
- (PluginLoadStatus)pluginloadStatus:(NSString*)pluginURL;

// 下載插件
- (void)downloadPlugin:(NSString*)pluginURL;

// 加載插件
- (void)loadPluginName:(NSString*)frameworkName
                   nav:(AINavigationController*)navVC
      enterVCClassName:(NSString*)className;

// 加載插件
- (UIViewController<AIPluginProtocol> *)loadPluginName:(NSString*)frameworkName enterVCClassName:(NSString*)className;

@end

(2)AIPluginTools:framework資源加載工具類

//
//  AIPluginTools.h
//  AIBase
//
//  Created by wuyoujian on 2017/6/21.
//  Copyright © 2017年 Asiainfo. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "../Owns/AICommonDef.h"

@interface AIPluginTools : NSObject

AISINGLETON_DEF(AIPluginTools,SharedObj);

// 從framework根目錄下加載圖片
- (UIImage *)roadImageWithName:(NSString *)name;

// 從framework根目錄下的包名:@param bunleName 中加載圖片,例如,res.bundle
- (UIImage *)roadImageWithName:(NSString *)name inResBundle:(NSString*)bundleName;

// 從矢量圖加載圖片
- (UIImage *)roadVectorImageWithName:(NSString *)name;

// 從framework根目錄下加載其他資源
- (NSData *)roadResWithName:(NSString*)name;

// 從framework根目錄下的包名:@param bunleName 中加載其他資源,例如,res.bundle
- (NSData *)roadResWithName:(NSString*)name inResBundle:(NSString *)bundleName;

// 返回資源路徑
- (NSString *)resPathWithName:(NSString*)name;

// 返回資源路徑
- (NSString *)resPathWithName:(NSString*)name inResBundle:(NSString *)bundleName;


@end

iOS平臺的能力待續。。。

2、android平臺提供的能力

目前android平臺的能力提供僅滿足crm常用的能力,後面陸續新增能力,在封裝android能力的時候,我們是全部採用代碼來實現控件,資源文件能實現編碼的採用編碼。

1)自定義證件拍照控件類RectCameraActivity

使用範例:

// 拍照
    @JavascriptInterface
    @NotProguard
    public void JN_Photograph(String functionName) {
        final String  mFunctionName = functionName;
        final String checkPermissinos [] = {Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE};
        PermissionUitls.mContext = getActivity();
        if(!PermissionUitls.isGetAllPermissionsByList(checkPermissinos) ) {
            new AlertDialog
                    .Builder(getActivity())
                    .setTitle("提示信息")
                    .setMessage("該功能需要您接受應用對一些關鍵權限(拍照)的申請,如之前拒絕過,可到手機系統的應用管理授權設置界面再次設置。")
                    .setPositiveButton("確認", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            checkPermission(mFunctionName,PermissionUitls.PERMISSION_CAMERA_CODE,checkPermissinos);
                        }
                    }).show();
        } else {

            jumpToRectCameraActivity(functionName);
        }
    }

    private void jumpToRectCameraActivity(String functionName) {
        Intent intent = new Intent(getActivity(), RectCameraActivity.class);
        intent.putExtra("functionName",functionName);
        intent.putExtra("fileId","fileId");
        getActivity().startActivityForResult(intent, 101);
    }

2)手寫控件類AISignatureView

它是一個標準的View類,可以類似於系統的View一樣的使用方式;他提供保存手寫圖片、獲取手寫圖片的Bitmap對象、刪除保存的圖片、設置筆的粗細、設置畫布背景、設置畫筆顏色等等能力;

3)手勢密碼控件類AIGesturePasswordLayout

它是一個標準的View類,用法同系統的View,下面我們給一份使用純代碼佈局的範例:

mGesturePasswordLayout = new AIGesturePasswordLayout(this);
        mGesturePasswordLayout.setGravity(Gravity.CENTER_VERTICAL);
        mGesturePasswordLayout.setBackgroundColor(0x00ffffff);
        mGesturePasswordLayout.setOnGestureLockViewListener(mListener);

        //
        tvParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.MATCH_PARENT);
        mRelativeLayout.addView(mGesturePasswordLayout,tvParams);

4)掃碼控件類CaptureActivity

這個控件是基於ZXing開源庫來封裝的。
使用範例:

private void ToScanCode2(int type) {
        //跳轉掃描頁面
        Intent intent = new Intent(getActivity(), CaptureActivity.class);
        intent.putExtra("type",type);
        getActivity().startActivityForResult(intent,SCAN_BAR_CODE_REQUEST_CODE);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章