React Native 實現從瀏覽器或其餘APP喚醒APP並跳轉指定頁面

原文地址:http://liu-hang.cn/2019/06/04/183-RN-open-app-except-page-from-webpage-or-otherapp/html

APP環境

  • react 0.59.5
  • react-navigation 3.9.1
  • react-navigation-redux-helpers 3.0.2

React Native 實現

我使用 react-navigation 來管理路由,react-navigation自己支持 Deep Linking,可是我使用 react-navigation-redux-helpers 組件將路由也封裝在 redux 下了,因此 react-navigation 自己的 deep-linking 功能就不能用了,在 react-navigation-redux-helpers 的 issue 下面我找到了其餘的解決方案。react

// 爲了監聽APP從後臺喚起的行爲,因此我選擇使用 AppState 接口,而後使用 Linking 獲取 url,而後將獲取到的地址初步解析提交給 LinkRoutes 方法
import { Linking, AppState } from 'react-native'
import LinkRoutes from './src/routes/linkRoutes'
...
componentDidMount(){
  AppState.addEventListener('change', this._handleAppStateChange)
}
componentWillUnmount(){
  AppState.removeEventListener('change', this._handleAppStateChange)
}
_handleAppStateChange = (nextAppState) => {
  if(nextAppState==='active'){
    Linking.getInitialURL().then(res => {
      if(!!res){
        LinkRoutes(res.split(':/')[1])
      }
    })
  }
}
...
複製代碼
// LinkRoutes 的實現,使用了 path-parser 作 url 解析,而後維護 APP 內須要跳轉的頁面的列表,而後調用 react-navigation 的navigate 方法,使用 dispatch 實現跳轉到指定頁面
import PathParser from 'path-parser'
import { NavigationActions } from 'react-navigation'
import store from '../reducers'
import _ from 'lodash'

const paths = [
  {
    routeName: 'Page',
    path: new PathParser('/page')
  }
]

const findPath = url => {
  let idx = _.findIndex(paths, p => {
    return p.path.test(url)
  })
  return idx > -1 ? paths[idx] : false
}

export default url => {
  const pathObj = findPath(url)
  if(!pathObj) return
  const navigateAction = NavigationActions.navigate({
    routeName: pathObj.routeName,
    params: pathObj.path.test(url)
  })
  store.dispatch(navigateAction)
}
複製代碼

iOS配置

// 修改 AppDelagate.m,添加
#if __IPHONE_OS_VERSION_MAX_ALLOWED > 100000
// 最新版本系統回調
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
  BOOL result = [[UMSocialManager defaultManager]  handleOpenURL:url options:options];
  if (!result) {
    // 其餘如支付等SDK的回調
  }
  return result;
}
#endif

// 支持全部iOS系統,此方法在swift4.1(Xcode 9.3)已廢棄,Objective-C項目不影響。
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
  BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url sourceApplication:sourceApplication annotation:annotation];
  if (!result) {
    // 其餘如支付等SDK的回調
  }
  return result;
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
  BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url];
  if (!result) {
    // 其餘如支付等SDK的回調
  }
  return result;
}
複製代碼

而後,修改 Url Types,添加 myappandroid

測試指令git

xcrun simctl openurl booted myapp://
複製代碼

iOS 使用模擬器是 Linking 捕捉不到 url,因此我是打包後在手機上測試的github

Android配置

在 .MainActivity 下添加配置,還能夠設置host以及path等,可是由於我是經過RN作解析,這裏就不加了web

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="myapp" />
</intent-filter>
複製代碼

測試指令shell

adb shell am start -W -a android.intent.action.VIEW -d "myapp://" com.myapp
複製代碼

參考文章

相關文章
相關標籤/搜索