iOS 热更新 SDK 使用指南

BuglyHotfix SDK v2.0 及以上版本不包含 JSPatch

SDK 集成

BuglyHotfix 提供两种集成方式供开发者选择:

  • 通过 CocoaPods 集成
  • 手动集成

BuglyHotfix iOS SDK 最低兼容 iOS 系统版本 iOS 7.0

BuglyHotfix 已经包含 Bugly 的所有功能,如果已经集成 Bugly SDK,请移除 Bugly 并替换成 BuglyHotfix 。

通过 CocoaPods 集成

在工程的Podfile里面添加以下代码:

pod 'BuglyHotfix'

保存并执行pod install,然后用后缀为.xcworkspace的文件打开工程。

注意:

命令行下执行pod search BuglyHotfix,如无法搜索到或搜索到的BuglyHotfix不是最新的版本,请先执行pod repo update更新本地的 spec-repositories 。

关于CocoaPods的更多信息请查看 CocoaPods官方网站

手动集成

  • 下载 BuglyHotfix iOS SDK
  • 拖拽BuglyHotfix.framework文件到 Xcode 工程内(请勾选Copy items if needed选项)
  • 添加以下依赖库
    • SystemConfiguration.framework
    • Security.framework
    • libz.tbd
    • libc++.tbd

JSPatch 集成

  • 下载 JSPatch 或 直接使用 BuglyHotfix SDK 压缩包内的 JSPatch 版本

  • 把下列文件拖入 Xcode 工程内(请勾选Copy items if needed选项)

    • JPEngine.h
    • JPEngine.m
    • JSPatch.js
  • 在工程内的Prefix Header(后缀为.pch)的文件内 #include "BuglyHotfixConfuse_pch.h" ,如工程内没有 pch 文件请参见这篇文章配置。

初始化SDK

导入头文件

在工程的AppDelegate.m文件导入头文件

#import <BuglyHotfix/Bugly.h>
#import <BuglyHotfix/BuglyMender.h>
#import "JPEngine.h"

如果是Swift工程,请在对应bridging-header.h中导入,Bugly 2.4.7 或 BuglyHotfix 2.0 及以上 SDK 可以直接 import Bugly

初始化 BuglyHotfix

在工程AppDelegate.mapplication:didFinishLaunchingWithOptions:方法中初始化 BuglyHotfix,示例代码如下:

  • Objective-C
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self configBugly];
    return YES;
}

- (void)configBugly {
    //初始化 Bugly 异常上报
    BuglyConfig *config = [[BuglyConfig alloc] init];
    config.delegate = self;
    config.debugMode = YES;
    config.reportLogLevel = BuglyLogLevelInfo;
    [Bugly startWithAppId:@"900001055"
#if DEBUG
        developmentDevice:YES
#endif
                   config:config];

    //捕获 JSPatch 异常并上报
    [JPEngine handleException:^(NSString *msg) {
        NSException *jspatchException = [NSException exceptionWithName:@"Hotfix Exception" reason:msg userInfo:nil];
        [Bugly reportException:jspatchException];
    }];
    //检测补丁策略
    [[BuglyMender sharedMender] checkRemoteConfigWithEventHandler:^(BuglyHotfixEvent event, NSDictionary *patchInfo) {
        //有新补丁或本地补丁状态正常
        if (event == BuglyHotfixEventPatchValid || event == BuglyHotfixEventNewPatch) {
            //获取本地补丁路径
            NSString *patchDirectory = [[BuglyMender sharedMender] patchDirectory];
            if (patchDirectory) {
                //指定执行的 js 脚本文件名
                NSString *patchFileName = @"main.js";
                NSString *patchFile = [patchDirectory stringByAppendingPathComponent:patchFileName];
                //执行补丁加载并上报激活状态
                if ([[NSFileManager defaultManager] fileExistsAtPath:patchFile] &&
                    [JPEngine evaluateScriptWithPath:patchFile] != nil) {
                    BLYLogInfo(@"evaluateScript success");
                    [[BuglyMender sharedMender] reportPatchStatus:BuglyHotfixPatchStatusActiveSucess];
                }else {
                    BLYLogInfo(@"evaluateScript failed");
                    [[BuglyMender sharedMender] reportPatchStatus:BuglyHotfixPatchStatusActiveFail];
                }
            }
        }
    }];
}
  • Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    configBugly()
    return true
}

private func configBugly() {
    let buglyConfig = BuglyConfig()
    buglyConfig.debugMode = true
    buglyConfig.reportLogLevel = .info
    Bugly.start(withAppId: "900001055",config:buglyConfig)

    JPEngine.handleException { (msg) in
        let exception = NSException(name: NSExceptionName(rawValue: "Hotfix Exception"), reason: msg, userInfo: nil)
        Bugly.report(exception)
    }

    BuglyMender.shared().checkRemoteConfig { (event:BuglyHotfixEvent, info:[AnyHashable : Any]?) in
        if (event == BuglyHotfixEvent.patchValid || event == BuglyHotfixEvent.newPatch) {
            let patchDirectory = BuglyMender.shared().patchDirectory() as NSString
            let patchFileName = "main.js"
            let patchFilePath = patchDirectory.appendingPathComponent(patchFileName)
            if (FileManager.default.fileExists(atPath: patchFilePath) && JPEngine.evaluateScript(withPath: patchFilePath) != nil) {
                BuglyLog.level(.info, logs: "evaluateScript success")
                BuglyMender.shared().report(.activeSucess)
            }else {
                BuglyLog.level(.error, logs: "evaluateScript fail")
                BuglyMender.shared().report(.activeFail)
            }
        }
    }
}

发布补丁

一. 开发环境测试

  • 将本地测试通过的main.js文件压缩成zip,点击 Bugly 平台 热更新 功能的发布新补丁 (热更新菜单在应用升级模块下)

弹出新建补丁窗口

选择目标版本(即应用版本)及开发设备,其它按默认值进行下发。

  • 运行应用,测试补丁是否正常下发且生效,如 Bugly 成功应用了补丁,则会在控制台输出加载日志
[Bugly][Info] Hotfix: evaluated script [version: 1]

二. 正式发布

点击 Bugly 平台上对应补丁的编辑按钮,按需选择全量设备自定义规则进行正式下发。


常见问题

  • BuglyHotfix SDK 集成后编译冲突

请检查是否集成了 Bugly.framework, BuglyHotfix 已经包含了 Bugly 的所有能力,所以只需去掉 Bugly.framework 即可。

  • 版本选择列表内没有我的版本

目标版本列表只显示集成了 BuglyHotfix SDK 的应用版本,所以如果没有出现请尝试集成 SDK 后先运行一下 App,然后再刷新页面尝试上传。

  • 如何获取补丁的信息?

可以通过下述 SDK 提供的 API 查询当前生效的补丁信息,如打开了测试本地 js,则无相关信息

+ (NSDictionary *)currentPatchInfo;

返回的结构如下:

 {
 @"patchVersion":"补丁版本号",
 @"patchDesc":"补丁备注信息",
 @"patchDirectory":"补丁文件路径",
 @"patchUpdateTime":"补丁更新时间"
 }
  • Bugly 如何保证补丁的安全性?

Bugly 全程通过 HTTPS 通讯,包括补丁文件的下发,确保补丁传输过程不被篡改。

  • JSPatch 上架问题

Bugly 只提供补丁的管理,下发等能力,不包含补丁的具体应用,如需要混淆 JSPatch ,可以参考 DEMO 中的方式。