HarmonyOS鸿蒙Next中应用切换到后台后VPN功能异常如何解决

HarmonyOS鸿蒙Next中应用切换到后台后VPN功能异常如何解决

【问题现象】

应用集成了VPN功能,且已申请后台长时任务,但是在转入后台运行时,VPN引流功能失效,进而导致需要依赖VPN通道访问的业务异常。

【背景知识】

【定位思路】

从问题现象可以看到,主要原因是没有对VPN隧道进行保护。可以参考第2节中 “VPN连接”,对VPN隧道进行保护。

点击放大

【解决方案】

1. 方案说明:

参照第2节中VPNExtension参考知识和VPN连接,对以下几个文件中的代码进行改造:

  1. MyVpnExtAbility.ts
  2. Index.ets
  3. build-profile.json5

2. 具体代码如下:

(1)MyVpnExtAbility.ts

导入相关模块:

import Want from '@ohos.app.ability.Want';
import VpnExtensionAbility from '@ohos.app.ability.VpnExtensionAbility';
import vpn_client from 'libvpn_client.so';
import vpnExt from '@ohos.net.vpnExtension';
import hilog from '@ohos.hilog';
import common from '@ohos.app.ability.common';

定义TAG和全局变量:

const TAG: string = "[MyVpnExtAbility]";
let g_tunFd = -1;
let g_tunnelFd = -1;

MyVpnExtAbility类主体:

export default class MyVpnExtAbility extends VpnExtensionAbility {
  private VpnConnection: vpnExt.VpnConnectionExt
  private vpnServerIp: string = '192.168.85.185';
  private tunIp: string = '10.0.0.8';
  private blockedAppName: string = 'com.example.testvpn';

  onCreate(want: Want) {
    console.info(TAG, `xdw onCreate, want: ${want.abilityName}`);
    this.VpnConnection = vpnExt.createVpnConnection(this.context);
    console.info("wmw createVpnConnection success")
    this.CreateTunnel();
    this.Protect();
    console.info("xdw step4");
  }

  onRequest(want: Want, startId: number) {
    console.info(TAG, `xdw onRequest, want: ${want.abilityName}`);
  }

  onConnect(want: Want) {
    console.info(TAG, `xdw onConnect, want: ${want.abilityName}`);
    let abilityName: string = want.parameters.abilityName.toString();
    let bundleName: string = want.parameters.bundleName.toString();
    return null;
  }

  onDisconnect(want: Want) {
    console.info(TAG, `xdw onDisconnect, want: ${want.abilityName}`);
  }

  onDestroy() {
    console.info(TAG, `xdw onDestroy`);
    this.Destroy();
  }

  Destroy() {
    hilog.info(0x0000, 'developTag', '%{public}s', 'vpn Destroy');
    vpn_client.stopVpn(g_tunnelFd);
    this.VpnConnection.destroy().then(() => {
      hilog.info(0x0000, 'developTag', '%{public}s', 'vpn Destroy Success');
    }).catch((err: Error) => {
      hilog.error(0x0000, 'developTag', 'vpn Destroy Failed: %{public}s', JSON.stringify(err) ?? '');
    })
  }

  CreateTunnel() {
    console.info("xdw step1")
    g_tunnelFd = vpn_client.tcpConnect(this.vpnServerIp, 8888);
  }

  Protect() {
    console.info("xdw step2")
    hilog.info(0x0000, 'developTag', '%{public}s', 'vpn Protect');
    this.VpnConnection.protect(g_tunnelFd).then(() => {
      hilog.info(0x0000, 'developTag', '%{public}s', 'vpn Protect Success');
      this.SetupVpn();
    }).catch((err: Error) => {
      hilog.error(0x0000, 'developTag', 'vpn Protect Failed %{public}s', JSON.stringify(err) ?? '');
    })
  }

  SetupVpn() {
    console.info("xdw step3")
    hilog.info(0x0000, 'developTag', '%{public}s', 'vpn SetupVpn');

    class Address {
      address: string;
      family: number;

      constructor(address: string, family: number) {
        this.address = address;
        this.family = family;
      }
    }

    class AddressWithPrefix {...}

    class Config {...}

    let config = new Config(this.tunIp, this.blockedAppName);

    try {
      this.VpnConnection.create(config, (error, data) => {
        g_tunFd = data;
        hilog.error(0x0000, 'developTag', 'tunfd: %{public}s', JSON.stringify(data) ?? '');
        vpn_client.startVpn(g_tunFd, g_tunnelFd);
      })
    } catch (error) {
      hilog.error(0x0000, 'developTag', 'vpn setUp fail: %{public}s', JSON.stringify(error) ?? '');
    }
  }
}

AddressWithPrefix部分定义:

class AddressWithPrefix {
  address: Address;
  prefixLength: number;
  constructor(address: Address, prefixLength: number) {
    this.address = address;
    this.prefixLength = prefixLength;
  }
}

Config部分定义:

class Config {
  addresses: AddressWithPrefix[];
  mtu: number;
  dnsAddresses: string[];
  trustedApplications: string[];
  blockedApplications: string[];
  constructor(tunIp: string, blockedAppName: string) {
    this.addresses = [new AddressWithPrefix(new Address(tunIp, 1), 24)];
    this.dnsAddresses = ["114.114.114.114"];
    this.trustedApplications = [];
    this.blockedApplications = [];
  }
}

(2)Index.ets

import common from '@ohos.app.ability.common'
import Want from '@ohos.app.ability.Want';
import vpnext from '@ohos.net.vpnExtension';

let context = getContext(this) as common.VpnExtensionContext;
let want: Want = {
  deviceId: "",
  bundleName: "com.example.testvpn",
  abilityName: "MyVpnExtAbility",
};

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold).onClick(() => {
          console.info("xdw btn click")
        })
        Button('Start Extension').onClick(() => {
          console.info("xdw btn start")
          vpnext.startVpnExtensionAbility(want)
        }).width('70%').fontSize(45).margin(16)

        Button('Stop Extension').onClick(() => {
          console.info("xdw btn end")
          vpnext.stopVpnExtensionAbility(want)
        }).width('70%').fontSize(45).margin(16)
      }.width('100%')
    }.height('100%')
  }
}

(3)build-profile.json5

{
  "apiType": 'stageMode',
  "buildOption": {
    "externalNativeOptions": {
      "path": "./src/main/cpp/CMakeLists.txt",
      "arguments": "",
      "cppFlags": "",
      "abiFilters": ["arm64-v8a", "x86_64"]
    }
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS"
    },
    {
      "name": "ohosTest",
    }
  ]
}

【总结】

对集成了VPN功能的应用而言,如果其VPN功能不稳定,就尤其需要注意对VPN隧道的保护。可以考虑使用系统提供的VPN增强功能,详情可参考相关官方文档以及上述样例代码实现,避免VPN功能失效等异常情况的发生。


更多关于HarmonyOS鸿蒙Next中应用切换到后台后VPN功能异常如何解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中应用切换到后台后VPN功能异常如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,应用切换到后台后VPN功能异常

在HarmonyOS鸿蒙Next中,应用切换到后台后VPN功能异常,可能是由于系统对后台应用的资源管理策略导致的。鸿蒙系统为了优化性能和电池续航,可能会限制后台应用的网络访问权限,从而影响VPN功能的正常运行。

要解决这个问题,可以尝试以下方法:

  1. 检查应用的后台权限:确保应用在后台运行时具有必要的网络访问权限。可以在“设置” -> “应用管理”中找到相关应用,检查其后台权限设置。

  2. 启用后台运行白名单:将VPN应用添加到系统的后台运行白名单中,以防止系统在应用切换到后台时限制其网络访问。可以在“设置” -> “电池” -> “应用启动管理”中进行配置。

  3. 更新系统和应用:确保系统和VPN应用都更新到最新版本,以获取最新的功能优化和问题修复。

  4. 检查VPN配置:确认VPN配置是否正确,包括服务器地址、认证信息等。错误的配置可能导致VPN在后台无法正常工作。

  5. 重启设备:有时简单的重启操作可以解决临时的系统或应用问题。

如果以上方法无法解决问题,可能需要进一步分析日志或联系应用开发者进行排查。

回到顶部