H5在浏览器跳转到App
- 配置URL Schemes
IOS Info.plist
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>xxxx</string>
</array>
</dict>
</array>
Android AndroidManifest.xml
<intent-filter>
<data android:scheme="xxxx" android:host="com.aaa.bbb" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
- h5跳转
通过window.location.href = xxxxx的方式跳转
const openApp = (isIOS, extinfo?: string) => {
if (isIOS) {
// link 就是 window.location.href = xxxxx;
link(`xxxx://${extinfo || ""}`);
} else {
link(`xxxx://com.aaa.bbb/${extinfo || ""}`);
}
};
- 跳转失败打开应用市场
是没法知道有没有跳转App成功的,设置定时器3秒以后跳转应用市场
const open = () => {
openApp(isIOS);
window.addEventListener("visibilitychange", () => {
const hidden = window.document.hidden || window.document["mozHidden"] || window.document["msHidden"] || window.document["webkitHidden"];
if (!hidden) {
window.timer && clearTimeout(window.timer);
}
});
window.timer && clearTimeout(window.timer);
window.timer = setTimeout(() => {
// 打开市场
// IOS 跳 AppStore https://itunes.apple.com/us/app/idxxxxxxxxxx
// Android 可以根据品牌 比如小米 mimarket://details?id=com.aaa.bbb,还可以跳应用宝 https://sj.qq.com/appdetail/com.aaa.bbb
openMarket();
}, 3000);
};
微信内H5拉起App
https://open.weixin.qq.com/
wx-open-launch-app
Web
验证微信Api
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [
"updateAppMessageShareData",
"updateTimelineShareData",
], // 必填,需要使用的JS接口列表
openTagList: [
'wx-open-launch-weapp',
'wx-open-launch-app'
], // 可选,需要使用的开放标签列表
});
import React from "react";
const LaunchApp: React.FC<{
appid: string;
onError?: () => void;
extinfo?: string;
}> = (props) => {
const launchApp = React.useRef<any>();
const functions = React.useRef<any>({});
...
React.useEffect(() => {
if (launchApp.current) {
if (functions.current.error) {
// "launch" 是拉起App成功
launchApp.current.removeEventListener("error", functions.current.error);
}
functions.current = {
...functions.current,
error: (x) => {
// 打开失败 跳转应用市场
props.onError && props.onError();
}
};
launchApp.current.addEventListener("error", functions.current.error);
}
return () => {
if (launchApp.current && functions.current.error) {
launchApp.current.removeEventListener("error", functions.current.error);
}
};
}, [
props.onError
]);
return <wx-open-launch-app
ref={launchApp}
id="launch-btn"
appid={props.appid}
extinfo={props.extinfo}
style={{
position: "absolute",
width: '100%',
height: '100%',
left: 0,
top: 0,
bottom: 0,
right: 0,
zIndex: 9999
}}
>
<script type="text/wxtag-template">
<div style={{
position: "absolute",
width: '100%',
height: '100%',
top: 0,
left: 0,
zIndex: 1
}}>
</div>
</script>
</wx-open-launch-app>;
};
export default LaunchApp;
Android
- AndroidManifest
在AndroidManifest.xml添加
<activity
android:name=".wxapi.WXEntryActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:exported="true"
android:taskAffinity="com.aaa.bbb"
android:launchMode="singleTask">
</activity>
- WeChatCallback
package com.aaa.bbb.wxapi;
public interface WeChatCallback {
void onResult();
}
- WeChatModule.java(
initDeepLink
和setDeepLinkCallback
)
在WeChatModule.java 写setDeepLinkCallback和initDeepLink
...
import com.facebook.react.bridge.Callback;
import com.aaa.bbb.wxapi.WeChatCallback;
...
public static Callback linkCallback = null;
public static WeChatCallback linkCacheCallback = null;
...
...
// 回调
@ReactMethod
private void setDeepLinkCallback(Callback cb) {
WeChatModule.linkCallback = cb;
}
// 等到App加载完成后处理冷启动
@ReactMethod
private void initDeepLink() {
if (WeChatModule.linkCacheCallback == null) {
Log.e("wxLog:H5打开", "非冷启动");
} else {
WeChatModule.linkCacheCallback.onResult();
}
}
...
- WXEntryActivity.java
package com.aaa.bbb.wxapi;
...
import com.aaa.bbb.wxapi.WeChatModule; // <=
import com.aaa.bbb.wxapi.WeChatCallback; // <=
import com.aaa.bbb.MainActivity; // <=
...
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
private static final String TAG = "WXEntryActivity";
private IWXAPI api;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 判断是否是冷启动
if (WeChatModule.modules.isEmpty()){
Intent intent = new Intent(WXEntryActivity.this, MainActivity.class);
startActivity(intent);
// 冷启动延迟推送微信参数
WeChatModule.linkCacheCallback = new WeChatCallback() {
@Override
public void onResult() {
// 处理结果
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(() -> {
__start();
scheduler.shutdown();
}, 2, TimeUnit.SECONDS);
}
};
} else{
__start();
}
finish();
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq baseReq) {
WritableMap map = Arguments.createMap();
if (baseReq.getType() == ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX) {
// 处理参数
ShowMessageFromWX.Req req = (ShowMessageFromWX.Req) baseReq;
map.putString("type", "WX_OPEN.Resp");
map.putString("extinfo", req.message.messageExt);
WeChatModule.linkCallback.invoke(map);
} else {
...
}
}
...
private void __start() {
api = WXAPIFactory.createWXAPI(this, Const.APP_ID);
api.handleIntent(getIntent(), this);
}
}
IOS
- GlobalManager设置全局变量用来判断是否是冷启动
// GlobalManager.h
#import <Foundation/Foundation.h>
@interface GlobalManager : NSObject
@property (nonatomic, assign) BOOL skipCold;
+ (instancetype)sharedManager;
@end
// GlobalManager.m
#import "GlobalManager.h"
@implementation GlobalManager
+ (instancetype)sharedManager {
static GlobalManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[self alloc] init];
});
return sharedManager;
}
- (instancetype)init {
self = [super init];
if (self) {
_skipCold = NO;
}
return self;
}
@end
- WeChatLib.m(
initDeepLink
)
// skipCold = YES 表示初始化完成了,可以跳过冷启动判断
RCT_EXPORT_METHOD(initDeepLink){
[GlobalManager sharedManager].skipCold = YES;
}
- WeChatLib.m(
onReq
)
-(void) onReq:(BaseReq*)req
{
if ([req isKindOfClass:[LaunchFromWXReq class]]) {
LaunchFromWXReq *launchReq = req;
NSString *appParameter = launchReq.message.messageExt;
NSMutableDictionary *body = @{@"errCode":@0}.mutableCopy;
body[@"type"] = @"LaunchFromWX.Req";
body[@"extMsg"] = appParameter;
...
[self sendEventName:RCTWXEventNameWeChatReq body:body];
}
}
- AppDelegate.m
#import "WeChatLib.h"
#import "GlobalManager.h"
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options {
...
// RCTWXAppID是appid
if ([url.scheme isEqualToString:RCTWXAppID]){
微信支付
if ([url.host isEqualToString:@"pay"]){
return [WXApi handleOpenURL:url delegate:[WeChatLib sharedInstance]];
}
BOOL skipCold = [GlobalManager sharedManager].skipCold;
if (skipCold) {
不是冷启动
[RCTLinkingManager application:app openURL:url options:options];
} else {
是冷启动 3秒以后再执行
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(timerFired:) userInfo:@{
@"url": url,
@"app": app,
@"options": options
} repeats:NO];
};
}
return [WXApi handleOpenURL:url delegate:self];
}
return [RCTLinkingManager application:app openURL:url options:options];
}
- (void)timerFired:(NSTimer *)timer {
NSDictionary *userInfo = timer.userInfo;
NSURL *url = userInfo[@"url"];
UIApplication *app = userInfo[@"app"];
NSDictionary *options = userInfo[@"options"];
[RCTLinkingManager application:app openURL:url options:options];
}
React Native
// 获取参数路由跳转或者其他操作
const open = (e?: {path?: string; params?: any}) => {
if (e && e.path) {
navigator.push(e.path, e.params);
}
};
// import {NativeModules, Platform, NativeEventEmitter} from 'react-native';
// import {Linking} from 'react-native';
const SCHEMES_ANDROID = "xxxx://com.aaa.bbb/";
const SCHEMES_IOS = "xxxx://";
const WeChatModule = NativeModules.WeChatModule;
const nativeEventEmitter = new NativeEventEmitter(WeChatModule);
// 注册微信
WeChatModule.registerApp(
"appid",
"universalLink",
).then((err) => {
if(!err && Platform.OS === 'android'){
// 监听Android微信获取参数
getWxAndroidDeepLink();
}
});
// 监听IOS微信获取参数
nativeEventEmitter.addListener("WeChat_Req", (resp) => {
if (resp.type === "LaunchFromWX.Req" && Platform.OS === 'ios') {
const [path] = resp.extMsg.split("?");
const params = resp.extMsg ? queryStringToParams(resp.extMsg) : {};
open({path, params});
}
...
});
// 监听Android微信获取参数
function getWxAndroidDeepLink () {
WeChatModule.setDeepLinkCallback((e) => {
if (e && e.type === "WX_OPEN.Resp" && e.extinfo) {
const [path] = e.extinfo.split("?");
const params = e.extinfo ? queryStringToParams(e.extinfo) : {};
open({path, params});
}
getWxAndroidDeepLink();
});
}
// 获取来自浏览器跳转带来的参数
const getDeepLinkFromWeb = (options?: {url?: string}) => {
if (options && options.url) {
const SCHEME = Platform.OS === "android" ? SCHEMES_ANDROID : SCHEMES_IOS;
if (options.url.match(SCHEME)) {
const url = options.url.replace(SCHEME, "");
const [path] = url.split("?");
// 字符串转化为params对象
const params = queryStringToParams(url);
open({path, params});
}
}
};
// 初始化(监听浏览器获取参数)
const initRouteFromWeb = () => {
Linking.getInitialURL().then((url) => {
getDeepLinkFromWeb({url});
//初始化微信
WeChatModule.initDeepLink();
Linking.addEventListener("url", getDeepLinkFromWeb);
});
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。