Class Vpn

java.lang.Object
com.codename1.vpn.profile.Vpn

public final class Vpn extends Object

Installing and controlling a VPN configuration the operating system runs for you.

if (Vpn.isSupported()) {
    Vpn.install(new VpnProfile("vpn.example.com")
            .usernamePassword("alice", secret))
       .ready(v -> Vpn.start());
}
The tunnel is the platform's, not this app's

Nothing here carries packets. The configuration is handed to the operating system, which runs its own IKEv2 or IPsec client; the app starts it, stops it and watches it. Implementing the tunnel itself is a different and much larger undertaking -- see the note in the com.codename1.vpn package documentation -- and this API stays useful around it either way, for the install, the status and the control.

The user may be asked, and the app cannot skip the asking

install(VpnProfile) shows a system prompt when the platform wants consent, and there is no way around it: a declined prompt fails with VpnError.USER_DECLINED, which is an ordinary outcome and not an error to report to the user again.

It is NOT a prompt on every install. Android asks once and remembers, so replacing a profile in an app the user has already approved provisions and answers with nothing shown -- the port takes that path whenever provisionVpnProfile returns no consent intent. An app that treated each install as a fresh checkpoint, or that told the user a dialog was coming, was wrong in that case.

So: be ready for the prompt, and do not depend on it appearing.

One configuration per app

Both platforms give an app a single managed configuration, so install(VpnProfile) replaces whatever was there rather than adding to it.

  • Method Details

    • isSupported

      public static boolean isSupported()

      Whether this platform can install and control a VPN configuration.

      False on Android below API 30, and on every port with no VPN machinery. Note this is a different question from whether a VPN is running -- com.codename1.io.NetworkManager#isVPNActive() answers that one, on many more platforms and with no entitlement.

    • getCapabilities

      public static int getCapabilities()
      The VpnBridge.CAPABILITY_* mask this platform supports.
    • getStatus

      public static VpnStatus getStatus()
      Where the tunnel is right now.
    • install

      public static AsyncResource<Boolean> install(VpnProfile profile)
      Installs or replaces this app's configuration, after asking the user.
    • remove

      public static AsyncResource<Boolean> remove()
      Removes this app's configuration.
    • load

      public static AsyncResource<VpnProfile> load()

      Reads back the installed configuration, resolving null when none is installed.

      The result never carries the password -- the platform keeps it. See VpnProfile.getPassword().

      On Android this is this app's RECORD, not a platform read

      VpnManager provisions, deletes, starts and stops; it has no call that hands a profile back. So the description here is the one this app kept when it installed, and it can outlive the real thing -- the user removing the VPN in Settings, or app data restored onto a device that never had it, both leave the record saying a profile exists.

      It corrects itself the first time the platform contradicts it: a start or a stop that comes back "nothing is provisioned" drops the record and moves the status to NOT_CONFIGURED. An app that must be certain should start() rather than trust a description, and watch the status. iOS reads the real configuration and has no such gap.

    • start

      public static AsyncResource<Boolean> start()
      Brings the tunnel up.
    • stop

      public static AsyncResource<Boolean> stop()
      Takes the tunnel down.
    • addStatusListener

      public static void addStatusListener(VpnStatusListener l)
      Adds a status listener. Arrives on the EDT.
    • removeStatusListener

      public static void removeStatusListener(VpnStatusListener l)
      Removes a status listener, stopping delivery when the last one goes.