基于原生能力的跨应用跳转

场景描述

使用原生能力startability启动其他应用前,开发者需要判断目标应用是否安装,从而执行不同的逻辑,例如:

场景一:支付时商户根据实际情况去判断,拉起支付应用还是h5页面。

场景二:分享场景与支付场景,需要列出多个用户可跳转的应用。

业务诉求:

场景一:支付时商户根据实际情况去判断,拉起支付应用还是h5页面

显示效果:

1.支付应用存在,拉起支付应用。

2.支付应用不存在,拉起h5页面进行支付。

核心代码

1.在拉起方的module.json5文件中配置querySchemes字段,表示本应用可能会用到的scheme查询,比如这里配置的payapp代表本应用可以使用bundleManager.canOpenLink(),来查询schemepayapp的链接是否可以打开(payapp://xx?xx=1&yy=2

"module": {
  "querySchemes": [
  "payapp",
  ],
}

2.在被拉起方的module.json文件中的skill字段中配置该应用支持的scheme协议,表示这个应用可以通过此协议打开

"abilities": [
{
  "skills": [
  {
    "entities": [
    "entity.system.home"
    ],
    "actions": [
    "action.system.home"
    ],
    "uris": [
    {
      "scheme": 'payapp'
    }
    ],
  }
  ]
}
]

3.在拉起方中通过bundleManager.canOpenLink()判断该链接能否打开,可以打开的话跳转支付应用进行支付,不能打开的话跳转h5页面来下载应用或者支付。

// payapp:// 后的字段可以自定义,需要由被拉起方应用进行处理
let paylink = 'payapp://startpay?apppid=123456&page=xxx/pay&query=10';
let paydata = bundleManager.canOpenLink(paylink);
if (paydata) {
  let want: Want = {
    uri: paylink
  };
  let context = getContext(this) as common.UIAbilityContext;
  context.startAbility(want, (error: BusinessError) => {
    console.error(`error.code = ${error.code}`);
  });
} else {
  this.pageInfos.pushPath({ name: 'PayWeb' })
}

//PayWeb
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';
 
@Component
export struct PayWebInfo {
  @Consume('pageInfos') pageInfos: NavPathStack;
  webviewController: web_webview.WebviewController = new web_webview.WebviewController();
 
  aboutToAppear() {
    try {
      this.webviewController.loadUrl($rawfile("pay.html"));
    } catch (error) {
      let e: business_error.BusinessError = error as business_error.BusinessError;
      console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);
    }
  }
 
  build() {
    NavDestination() {
      Column() {
        Web({ src: $rawfile("pay.html"), controller: this.webviewController })
      }.width('100%').height('100%')
    }.hideTitleBar(true)
  }
}

4.被调用方在冷启动热启动的情况下都要拉起同一个支付页面,就需要在onNewWantonCreateonWindowStageCreate中都添加跳转支付页面的相关逻辑。

//定义一个接口接收want传入的数据
interface StartParm {
  bundleName?: string
  uriResult: uri.URI
  started: boolean
}
//将want数据存入
function parseStartWant(want: Want): StartParm | undefined {
  if (want.uri) {
    let startParam: StartParm = {
      bundleName: want.bundleName,
      uriResult: new uri.URI(want.uri),
      started: false
    }
    return startParam
  } else {
    return undefined
  }
}
​
export default class EntryAbility extends UIAbility {
  startParam?: StartParm
  ​
  // 冷热启动均执行,用于跳转支付页面
  action() {
    if (this.startParam && !this.startParam.started) {
      this.startParam.started = true
      let pageInfos = AppStorage.get<NavPathStack>("pageInfos") as NavPathStack;
      //判断支付页面是否存在
      let data =pageInfos.getIndexByName('PayPage')
      if ( data.length == 0 ) {
        pageInfos.pushPath({ name: 'PayPage' })
      }else  {
        pageInfos.removeByName('PayPage')
        pageInfos.pushPath({ name: 'PayPage' })
      }
    }
  }
  ​
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    this.startParam = parseStartWant(want)
    //本Demo通过AppStorage将传入的数据展示在页面上,例如消费应用,消费金额等
    AppStorage.setOrCreate<StartParm>("Param",this.startParam );
  }
  ​
  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    this.startParam = parseStartWant(want)
    //数据处理同onCreate
    AppStorage.setOrCreate<StartParm>("Param",this.startParam );
    //跳转支付页面
    this.action()
  }
 
  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      //由于时序问题,需要使用setTimeout保证页面压栈的顺序
      setTimeout(()=>{
        //跳转支付页面
        this.action()
      })
    });
  }
}

场景二:分享场景与支付场景,需要列出多个用户可跳转的应用

显示效果:

核心代码 

1.同场景一Step1,需要在querySchemes中配置需要进行跳转检测的应用。

"module": {
  ...
  "querySchemes": [
  "bank1",
  ...
  "bank9"
  ]
}

2.在拉起方中遍历想要跳转的所有应用,并在弹窗中显示可以被拉起的应用。

准备被拉起方的app信息,其中目标app的图标需要拉起方应用自己准备。uri字段规格详见文末的常见问题Q1。

private payApps: PayApp[] = [
  new PayApp('银行1', $r("app.media.startIcon"), 'bank1://xx?xx'),
  ...
  new PayApp('银行9', $r("app.media.startIcon"), 'bank9://xx?xx'),
]

添加按钮,点击出现支付应用列。

Button("跳转支付列表")
  .onClick(() => {
    if (this.dialogController != null) {
      this.dialogController.open()
    }
  })

添加自定义弹窗,定义弹窗以及弹窗中分割线的属性:

@State egDivider: DividerTmp = new DividerTmp(1, 10, 10, '# ffe9f0f0')
​
//增加一个类方便定义分割线属性
class DividerTmp {
  strokeWidth: Length = 1           //分割线宽度
  startMargin: Length = 10          //分割线距离左端长度
  endMargin: Length = 10            //分割线距离右端长度
  color: ResourceColor = '# ffe9f0f0'//分割线颜色
  ​
  constructor(strokeWidth: Length, startMargin: Length, endMargin: Length, color: ResourceColor) {
    this.strokeWidth = strokeWidth
    this.startMargin = startMargin
    this.endMargin = endMargin
    this.color = color
  }
}
​
//自定义弹窗
dialogController: CustomDialogController | null = new CustomDialogController({
  builder: CustomDialogExample({
    payApps: this.payApps,
    egDivider: this.egDivider
  }),
})

在弹窗显示之前判断应用是否已安装,在弹窗中显示已安装的应用,并实现点击跳转到该应用。

//每行app的信息
class PayApp {
  name: string;
  icon: Resource;
  link: string;
  installed: boolean = false
  ...
}
​
@CustomDialog
struct CustomDialogExample {
  @Prop payApps: PayApp[]
  @Prop egDivider: DividerTmp
  controller?: CustomDialogController
 
  aboutToAppear(): void {
    for (let item of this.payApps) {
      item.installed = bundleManager.canOpenLink(item.link)
    }
    this.payApps = this.payApps.filter((app) => app.installed)
  }
  ​
  build() {
    Column() {
      ...
      List() {
        ForEach(this.payApps, (item: PayApp) => {
          ListItem() {
            Row() {
              Image(item.icon).width(25).height(25).margin(10)
              Text(item.name).fontSize(20)
            }
            .onClick(() => {
              let context = getContext() as common.UIAbilityContext
              context.startAbility({ uri: item.link })
            })
            .justifyContent(FlexAlign.Start)
          }
        }, (item: PayApp) => item.name.toString())
      }
    }
  }
}

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值