天天看點

hbuilder 5+ ios離線打包跳轉微信小程式 微信原生包 hbuilder原生插件開發

由于5+已經停止更新了,官方的雖然有跳轉小程式的方法,但是試了幾個離線包都不成功,安卓倒是一次成功了,附上hbuilder文檔 調用微信小程式寫得夠簡潔的,簡直是垃圾!

注:以下文檔大部分是踩坑記錄,并無太多詳細步驟,前人的教程已經很詳細了。

一、申請Universal Link

附上簡書的教程:iOS Universal Link(通用連結)

已經很詳細了,就不再重複了

強調幾點:

  1. 需要https的連結;
  2. Universal Link中的appid是teamid+bundle id;
  3. 配置的連結普通打開時404也沒關系,safari中重新整理一下能提示跳轉資訊就行。
  4. 蘋果官方驗證universal link 的位址是:連結,裡面填的 https://domians/apple-app-site-association位址,不是universal link連結,這問題又浪費了我半個小時。最後一項提示如下是就是正常的了。
    hbuilder 5+ ios離線打包跳轉微信小程式 微信原生包 hbuilder原生插件開發
  5. 申請成功後需要重新生成profile,看看profile裡有包含associated domains行了,xcode是自動生成profile的,如果沒有,試試重新開機xcode,或者到資源庫裡面清空profile檔案,再切換回來xcode就會重新生成profile了。有很多教程是讓你去開發者中心看associated domains的是不是enable了,但我找不到那個頁面,估計是舊版的。
hbuilder 5+ ios離線打包跳轉微信小程式 微信原生包 hbuilder原生插件開發

二、申請微信應用

位址:微信開放平台

需要稽核通過的應用才能用,修改Universal Link不需要重新申請稽核。

三、接入微信sdk

官方文檔:IOS接入指南

詳細請看官方文檔。

1.注冊

在AppDelegate.m中的 didFinishLaunchingWithOptions方法中注冊,這裡的id是微信應用的id,不是小程式ID。自檢函數釋出時要登出掉。didFinishLaunchingWithOptions在離線包中已經存在,不要另外添加。

//在register之前打開log, 後續可以根據log排查問題
//    [WXApi startLogByLevel:WXLogLevelDetail logBlock:^(NSString *log) {
//        NSLog(@"WeChatSDK: %@", log);
//    }];
    
  
    NSLog(@"-----didFinishLaunchingWithOptions");
    //向微信注冊
    BOOL res = [WXApi registerApp:@"wx********"
                        universalLink:@"https://********/ulink/"];
 
    NSLog(@"-----registerApp:%@", res ? @"yes" : @"no");
 
//    //調用自檢函數
//    [WXApi checkUniversalLinkReady:^(WXULCheckStep step, WXCheckULStepResult* result) {
//        NSLog(@"-----%@, %u, %@, %@", @(step), result.success, result.errorInfo, result.suggestion);
//    }];
           

2.監聽處理Universal Link回調

實作三個微信sdk需要調用的方法,原樣複制即可,AppDelegate.m中已經存在,需要把huilder的給注釋掉,按方法名搜尋。注意!由于AppDelegate.m裡面代碼多,不要粘貼錯地方,裡面有兩個@implementation XXX  @end子產品:@implementation UINavigationController(Orient)@end  和      @implementation AppDelegate  @end。                                                                                  代碼需要放在@implementation AppDelegate  @end中。或者你放到原來方法的旁邊,被這個坑了三天,原生大佬勿噴,我不是很懂ios原生。不然會出現,跳轉到微信後,顯示正在連接配接,然後又跳回來,并提示PBItemCollectionServicer connection disconnected。自建函數第5步也會提示該錯誤。因為沒有正确處理微信的Universal Link回調方法。onResp監聽微信傳回app。

//
-(void)onResp:(BaseResp *)resp
{
    NSLog(@"-----onResp---");
     if ([resp isKindOfClass:[WXLaunchMiniProgramResp class]])
     {
          NSString *string = resp.errStr;
          NSLog(@"-----onResp:%@", string);
    
          // 對應JsApi navigateBackApplication中的extraData字段資料
     }
}

-(void) onReq:(BaseReq*)req
{
    NSLog(@"-----onReq---");
    if([req isKindOfClass:[GetMessageFromWXReq class]])
    {
        // 微信請求App提供内容, 需要app提供内容後使用sendRsp傳回
        NSString *strTitle = [NSString stringWithFormat:@"微信請求App提供内容"];
        NSString *strMsg = @"微信請求App提供内容,App要調用sendResp:GetMessageFromWXResp傳回給微信";


    }
    else if([req isKindOfClass:[ShowMessageFromWXReq class]])
    {
        ShowMessageFromWXReq* temp = (ShowMessageFromWXReq*)req;
        WXMediaMessage *msg = temp.message;

        //顯示微信傳過來的内容
        WXAppExtendObject *obj = msg.mediaObject;

        NSString *strTitle = [NSString stringWithFormat:@"微信請求App顯示内容"];
        NSString *strMsg = [NSString stringWithFormat:@"标題:%@ \n内容:%@ \n附帶資訊:%@ \n縮略圖:%u bytes\n\n", msg.title, msg.description, obj.extInfo, msg.thumbData.length];


    }
    else if([req isKindOfClass:[LaunchFromWXReq class]])
    {
        //從微信啟動App
        NSString *strTitle = [NSString stringWithFormat:@"從微信啟動"];
        NSString *strMsg = @"這是從微信啟動的消息";

    }
}
           
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    NSLog(@"-----handleOpenURL---");
    return  [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    NSLog(@"-----openURL---");
    return [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullable))restorationHandler {
    NSLog(@"-----continueUserActivity---");
    return [WXApi handleOpenUniversalLink:userActivity delegate:self];
}
           

 3.hbuilder自定義插件開發                                                                                                 

 頭部.h:

#include "PGPlugin.h"
#include "PGMethod.h"
#import <Foundation/Foundation.h>

@interface AlibabaRLSB : PGPlugin
- (void)LaunchMiniProgram:(PGMethod*)command;
@end
           

内容.m

#import "PGPlugin+AlibabaRLSB.h"  //引入頭部
#import <RPSDK/RPSDK.h>
#import "WXApi.h"


@implementation AlibabaRLSB

/**
 *啟動小程式
 */
- (void)LaunchMiniProgram:(PGMethod*)commands
{
    if ( commands ) {

        // CallBackid 異步方法的回調id,H5+ 會根據回調ID通知JS層運作結果成功或者失敗
        NSString* cbId = [commands.arguments objectAtIndex:0];
        NSString* path = [commands.arguments objectAtIndex:1];
        NSLog(@"小程式路徑path:%@", path);
        
        
        WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
        launchMiniProgramReq.userName = @"gh_******";  //拉起的小程式的username
        launchMiniProgramReq.path = path;    拉起小程式頁面的可帶參路徑,不填預設拉起小程式首頁,對于小遊戲,可以隻傳入 query 部分,來實作傳參效果,如:傳入 "?foo=bar"。
        launchMiniProgramReq.miniProgramType = 0; //拉起小程式的類型 0-正式版; 1-測試版; 2-體驗版
        
        return [WXApi sendReq:launchMiniProgramReq completion:^(BOOL success) {
            NSLog(@"拉起小程式結果=%d",success);
        }];
        
        // 運作Native代碼結果和預期相同,調用回調通知JS層運作成功并傳回結果
//        PDRPluginResult *resultShow = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsString:pResultString];
//
//        // 通知JS層Native層運作結果
//        [self toCallback:cbId withReslut:[resultShow toJSONString]];
         
    }
}



//擷取目前螢幕顯示的viewcontroller
- (UIViewController *)getCurrentVC
{
    UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    
    UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
    
    return currentVC;
}

- (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
{
    UIViewController *currentVC;
    
    if ([rootVC presentedViewController]) {
        // 視圖是被presented出來的
        
        rootVC = [rootVC presentedViewController];
    }

    if ([rootVC isKindOfClass:[UITabBarController class]]) {
        // 根視圖為UITabBarController
        
        currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];
        
    } else if ([rootVC isKindOfClass:[UINavigationController class]]){
        // 根視圖為UINavigationController
        
        currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];
        
    } else {
        // 根視圖為非導航類
        
        currentVC = rootVC;
    }
    
    return currentVC;
}

@end
           

我的元件名叫做AlibabaRLSB。下面那個getCurrentVC,這裡沒用到,用阿裡人臉識别時用到,就沒删,如果你要開發其他插件可能也會用到。userName 是小程式的原始ID,不是小程式ID。                                                                                                                                    注冊插件的寫法如下,hbuilder的文檔寫得很模糊,位置:PandoraApi.bundle->feature.plist。

hbuilder 5+ ios離線打包跳轉微信小程式 微信原生包 hbuilder原生插件開發

4.html頁面調用插件

function WXTools() {}

// 微信授權登入對象
WXTools.prototype.aweixin = undefined;
// 目前環境支援的所有授權登入對象
WXTools.prototype.auths = {};

WXTools.prototype.SuccessCallBack = undefined;
WXTools.prototype.FailCallBack = undefined;
WXTools.prototype.Options = undefined;

/*
 * 打開小程式
 */
WXTools.prototype.launchMiniProgram = function launchMiniProgram(_Options) {
	this.Options = _Options || {};
	this.MiniProgramPath = _Options.path;
	this.SuccessCallBack = this.Options.success;
	this.FailCallBack = this.Options.fail;
	if (window.plus.os.name == 'Android') {
		this.getShareService();
	} else {
		this.launchMiniProgram_IOS();
	}
}
/*
 * ios打開小程式
 */
WXTools.prototype.launchMiniProgram_IOS = function launchMiniProgram_IOS() {
    var that = this;
    var success = typeof that.SuccessCallBack !== 'function' ? null : function(args) {
        console.log("--SuccessCallBack---")
        console.log(JSON.stringify(args))
            //that.SuccessCallBack(args);
        },
        fail = typeof that.FailCallBack !== 'function' ? null : function(code) {
            console.log("--FailCallBack---")
            console.log(JSON.stringify(code))
            //that.FailCallBack(code);
        };
    callbackID = plus.bridge.callbackId(success, fail);
	
	if(!this.IsFirst_IOS){
		//跳轉回來時重新整理
		document.addEventListener("resume", function() {
			console.log("--小程式跳轉app---")
			that.SuccessCallBack && that.SuccessCallBack();
		}, false);
		this.IsFirst_IOS = true;
	}
	
	
    return plus.bridge.exec("AlibabaRLSB", "LaunchMiniProgram", [callbackID, this.MiniProgramPath]);
}

//擷取微信分享服務

WXTools.prototype.getShareService = function getShareService() {
	var that = this;
 
	that.shareauths = [];
	plus.share.getServices(function(services) {
		for (var i in services) {
			var service = services[i]
			that.shareauths[service.id] = service;
		}
		that.wxShare = that.shareauths['weixin'];
		that.launchMiniProgram_in(); //下一步授權
	}, function(e) {
		console.log("擷取登入授權服務清單失敗:" + JSON.stringify(e));
		that.FailCallBack && that.FailCallBack(e);
	});
}

WXTools.prototype.launchMiniProgram_in = function launchMiniProgram_in() {
	var that = this;
	if (!this.wxShare) {
		console.log("目前環境不支援微信操作");
		that.FailCallBack && that.FailCallBack({
			code: -1,
			message: "目前環境不支援微信操作"
		});
		return;
	}

	document.addEventListener("resume", function() {
		if (plus.runtime.arguments != "") {
			var re = {};
			try {
				re = JSON.parse(plus.runtime.arguments);
			} catch (e) {
				re = plus.runtime.arguments;
			}
			
			that.SuccessCallBack && that.SuccessCallBack(re);
		}
	});

	var herf = this.MiniProgramPath;
	this.wxShare.launchMiniProgram({
			id: 'gh_***c',
			path: herf, //跳轉到小程式的頁面并傳參
			type: 0  //0-正式版; 1-測試版; 2-體驗版
		},
		function(e) {},
		function(e) {
			console.log("目前環境不支援微信操作:" + JSON.stringify(e));
			that.FailCallBack && that.FailCallBack(e);
		})
}


var WXTool = new WXTools();
           

這裡的安卓是調用hbuilder的插件,ios是剛剛自己寫的插件。通過document.addEventListener("resume")監聽小程式跳轉回app,然後重新整理頁面;也可以通過監聽onResp,然後重新整理頁面,這種方法比較麻煩,我就懶得折騰了,自行研究。

5.踩坑

  1. 自檢函數用來測試挺好用的,如果加上自檢函數崩潰時,請檢查項目裡是不是加了兩個libWeChatSDK.a,離線包裡的微信sdk比較舊,可能沒有自檢函數。在Build Settings->Search Paths中可以檢視引入的libs位置。
  2. 出現未驗證應用:連結,常見問題自查,出問題社群99%都是丢給你這兩個連結,也确實有點用。