Pango Platform
HomeConsole
  • What is Pango Developer Platform
  • Getting started
    • Sign up on the Management Console
    • Create a new project
    • Switch projects
    • Change console settings
    • Edit your profile
    • Try out the demo app
    • Keep exploring
    • Deprecation and Sunset
  • Console details
    • Dashboard
      • General
      • Location loading
    • Users
      • User page
    • Active sessions
    • Network
      • Countries
      • Locations
      • Pools
        • Optimal location
        • Location rules
    • Settings
      • General
        • Project config description (JSON format)
          • Server selector (JSON format)
          • Request selector (JSON format)
      • Authentication methods
        • Auth Plugin requirements
      • VPN
        • General
        • VPN Bypass list
        • Client Networks
      • Member
    • Export Data
    • Log
  • SDK
    • Unified VPN SDK for Android
      • Setup
        • Application Setup
        • Proguard Rules, Notification, and Analytics Configurations
        • Backend URL Configuration
      • Usage
        • Initialization
        • VPN Interface
        • Backend interface
      • Features
        • Hydra Protocol
          • Location profile (Hydra only)
        • Custom sdk dependencies
        • Deferred VPN Service Initialization
        • Authentication
        • Client Network List (CNL)
        • OpenVPN transport
        • Wireguard Transport
        • Reconnection strategy
        • Single Protocol SDK
        • Killswitch
        • Domain route via VPN
        • Process route via VPN
        • Process Bypass
        • Domain Bypass
        • Traffic rules
        • VPN Node DNS Configuration
        • Multihop
          • Optimal Location
      • Exceptions
      • Version migration
      • Changelog
    • Unified VPN SDK for Apple
      • Setup
        • Application Setup
        • Network Extension Setup
          • Network Extension Setup for tvOS
        • Backend URL Configuration
      • Usage
        • Single Protocol SDK
        • Unified SDK
        • Logging
        • Decoding Encoded VPN SDK Logs
      • Features
        • Deferred VPN Service Initialization
        • Authentication
        • Wireguard Transport
        • Reconnection strategy
        • Killswitch
        • Domain Bypass
        • Multihop
          • Optimal Location
        • Client Network List (CNL)
        • Domain route via VPN
      • Changelog
      • API Reference
    • IPSEC VPN SDK for Apple
    • Unified VPN SDK for Windows
      • Setup
        • Backend URL Configuration
        • Service command line arguments
        • ARM Platform Support
      • Usage
        • CoreAPI
        • Events
        • Generating a Unique Device Identifier
        • Error processing
        • Pipe Messaging
      • Features
        • Traffic protection
          • Killswitch
          • Prevent IP Leaks
          • Block Local Networks
        • Other
          • Firewall
            • DNS Monitor
            • Process Bypass
            • Domain Bypass
            • Process route via VPN
            • Domain route via VPN
          • Throttling
          • Optimal Location
          • Common issues
        • Hydra Protocol
          • CustomDNS, UserDNS, MultiHop, VpnProfiles
        • OpenVPN Protocol
        • Wireguard Protocol
        • IPSec Protocol
      • Collecting Debug Logs
      • Changelog
    • Unified VPN SDK for Routers
      • SDK. Shared library.
      • Configuration Interface (CI)
        • Unix Domain Sockets CI
        • REST API CI
    • Unified VPN SDK Feature Comparison By Platform
    • Unified VPN SDK
      • Features
        • Personal Bridge
    • Tunnel Vision and Tunnel Crack Prevention
  • REST API
    • Partner API
  • Sample applications
    • Unified VPN SDK demo for Windows
    • Hydra VPN SDK demo for iOS
    • IPSEC VPN SDK demo for iOS
    • Unified VPN SDK demo for Android
    • Hydra VPN SDK demo for OpenWRT
    • OpenVPN configuration file
  • Resources
    • Use cases
      • Public VPN
      • Business VPN
        • Creating a Business VPN Project
        • Wi-Fi Security for Business
      • Application anti-blocking
    • How-to
      • Create a Firebase project for User Authentication
      • AWS CloudFront Distribution of the Platform URL
      • How can I get Shared Secret key from iTunes Connect for In-App Purchase
  • FAQ
    • General
      • VPN Platform Flow
      • What data is collected by the Platform?
      • What analytic data is collected by your SDK?
      • How the Platform restricts access to our data?
      • Why DNS Leak tests often indicate positive result?
      • Do we need to perform endpoint health checks?
      • How is the VPN exit node found?
      • How are streams re-marked if VPN is enabled/disabled on an active flow?
      • Is there a maximum number of supported devices?
      • Are both IPv4 and IPv6 supported?
      • What is the MTU of the tunnel?
      • Are any redundancy measures in terms of reliability provided?
      • Is there any load balancing?
      • Do you block broadcast and multicast to/from the VPN?
    • List of Open Source libs
Powered by GitBook
On this page
  • Proguard Rules
  • What is Proguard?
  • Benefits of using Proguard Rules
  • When to use Proguard Rules
  • Usage
  • Proguard Rules Explanation
  • Setting VPN Process Name
  • Enabling Java 8 Support
  • Configuring Notifications
  • Notifications for Different States
  • Notification Message and Title Fallback
  • Notification Click Intent
  • Updating Notification Preferences
  • Connected State Notification Placeholders
  • Disabling Notifications
  • Analytics

Was this helpful?

  1. SDK
  2. Unified VPN SDK for Android
  3. Setup

Proguard Rules, Notification, and Analytics Configurations

The documentation provides configuration and code snippets for integrating VPN capabilities into Android apps.

Proguard Rules

What is Proguard?

ProGuard is a tool used in Android development to optimize, shrink, and obfuscate the bytecode of Java and Kotlin applications. It's part of the Android build process and helps reduce the size of the APK, improve performance, and protect the code from reverse engineering by obfuscating class, method, and variable names. ProGuard processes the compiled bytecode before packaging the app for distribution.

Benefits of using Proguard Rules

Developers use Proguard rules to optimize their application, protect sensitive code from reverse-engineering, and reduce the size of the final APK (Android package). By stripping away unnecessary code, Proguard improves app performance and reduces memory usage. It is especially important for production builds, where security and performance are critical.

When to use Proguard Rules

Proguard rules should be used when preparing release builds of an Android app, especially if the app uses third-party libraries that rely on reflection (like JSON serialization libraries), or if the developer needs to optimize the app's size and security. They are less critical for debug builds but essential for production releases to ensure the app functions correctly while being as efficient and secure as possible.

Usage

  1. Copy the provided ProGuard rules into your project's proguard-rules.pro file.

  2. By default, minifyEnabled is set to false within the build.gradle (Module :app). You will need to go into build.gradle (Module :app) and set it as true:

Groovy

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

Kotlin

By default, isMinifyEnabled is set to false within the build.gradle (Module :app) . You will need to go into build.gradle.kts (Module :app) and set it as = true

android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
}

Proguard Rules Explanation

Proguard rules are included in sdk, but you can follow these steps if required:

  • Located the proguard-rules.pro file on the left hand side of Android Studio.

  • Double-click into this file

  • Copy the rules from the grey box below and paste them into the proguard-rules.pro file

-keep class * extends unified.vpn.sdk.ReportUrlProvider {
    public <init>(...);
}

-keep class * extends unified.vpn.sdk.BaseInfoCollector {
    public <init>(...);
}

-keep class * extends unified.vpn.sdk.TrackerTransportFactory {
    public <init>(...);
}

-keep class * extends unified.vpn.sdk.CredentialsSource {
    public <init>(...);
}

-keep class * extends unified.vpn.sdk.SdkTrackerDelegate {
    public <init>(...);
}
-keep enum unified.vpn.sdk.UnifiedSDKConfig$CallbackMode {
    *;
}

-keep class * extends unified.vpn.sdk.IStartConfigPatcher {
    public <init>(...);
}
-keep class * extends unified.vpn.sdk.ConfigPatcherFactory {
    public <init>(...);
}
-keep class * extends unified.vpn.sdk.IMiddleConfigPatcher {
    public <init>(...);
}

#DNSJava
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

-keepclassmembers class * implements javax.net.ssl.SSLSocketFactory {
    final javax.net.ssl.SSLSocketFactory delegate;
}

# https://stackoverflow.com/questions/56142150/fatal-exception-java-lang-nullpointerexception-in-release-build
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}
-dontwarn org.bouncycastle.jsse.BCSSLParameters
-dontwarn org.bouncycastle.jsse.BCSSLSocket
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
-dontwarn org.conscrypt.Conscrypt$Version
-dontwarn org.conscrypt.Conscrypt
-dontwarn org.conscrypt.ConscryptHostnameVerifier
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
-dontwarn org.openjsse.net.ssl.OpenJSSE
-dontwarn unified.vpn.sdk.HydraConnectionState

-keep class * extends unified.vpn.sdk.Daemon {
     public <init>(...);
 }

-dontwarn unified.vpn.sdk.KeyValueStorageImpl

-keep public class * extends unified.vpn.sdk.NetworkProbeFactory {
     public <init>(...);
 }

-keep class unified.vpn.sdk.PingService { *; }
-keep class unified.vpn.sdk.PingResult { *; }

# This dnsjava class uses old Sun API
-dontnote org.xbill.DNS.spi.DNSJavaNameServiceDescriptor
-dontwarn org.xbill.DNS.spi.DNSJavaNameServiceDescriptor

-keepclassmembers class org.xbill.DNS.Lookup {
    java.util.Map defaultCaches;
    org.xbill.DNS.Name[] defaultSearchPath;
    int defaultNdots;
}

-keep class * extends unified.vpn.sdk.WireguardPingJobFactory {
    public <init>(...);
}
-keepclassmembers class com.wireguard.** { *; }

-keepclassmembers class unified.vpn.sdk.HydraTransport$ApiHeaderListener {
    *** protect(...);
    *** onHdr(...);
}

-keep class com.anchorfree.hdr.** {*;}

-keep public class * extends unified.vpn.sdk.VpnException {
    *;
}

-keep public class * extends unified.vpn.sdk.CaptivePortalChecker {
    public <init>(...);
}

-keep public class * extends unified.vpn.sdk.TransportFactory {
    public <init>(...);
}

-keep class * extends unified.vpn.sdk.ReconnectExceptionHandler {
    public <init>(...);
}

Setting VPN Process Name

To set a custom process name for the VPN, add the following string resource to your source file:

  1. On the left hand side of Android Studio, click the folder res

  2. Then click on values

  3. Double click on </> strings.xml

  4. Paste the text below into that file:

<string name="vpn_process_name" translatable="false">:vpn</string>

Enabling Java 8 Support

If you are using Android Studio and selected a minimum SDK version of API 21 (Lollipop; Android 5.0), Java 8 will be configured by default for you. If for some reason it is not, please follow the steps listed below

The minimum version of Java that our SDK works with is Java 8. You can use Java 8 or higher (up to Java 21) to build your application.

To add Java 8 support to your project:

  1. On the left hand side of Android Studio, select build.gradle (Module: app) for Gradle projects or build.gradle.kts (Module: app) for Kotlin projects.

  1. update your build.gradle file with the following:

Kotlin

compileOptions {
   sourceCompatibility = JavaVersion.VERSION_1_8
   targetCompatibility = JavaVersion.VERSION_1_8
}

Groovy

compileOptions {
   sourceCompatibility = JavaVersion.VERSION_1_8
   targetCompatibility = JavaVersion.VERSION_1_8
}
  1. Paste the code snippet within the Android configuration block

Configuring Notifications

The SDK provides the ability to customize the notifications that appear during various stages of the VPN lifecycle. By utilizing the NotificationConfig.Builder class, you can configure how these notifications behave, what information they display, and how users can interact with them.

Notifications for Different States

The SDK allows you to customize the notification messages for various VPN states. This provides flexibility in messaging and helps keep users informed about what is happening with the VPN connection.

1. VPN Connected: When the VPN successfully connects, a notification is displayed.

builder.inConnected("Connected", "VPN is successfully connected.");

2. VPN Idle: When the VPN is not connected (idle state), display a different notification.

builder.inIdle("Not Connected", "VPN is currently disconnected.");

3. VPN Connecting: During the VPN connection process, you can show a "connecting" notification.

builder.inConnecting("Connecting", "Attempting to establish a VPN connection...");

4. VPN Paused (Waiting for Network Connection): This state occurs when the VPN is paused while waiting for a network connection (e.g., when switching from Wi-Fi to cellular data).

builder.inPause("Paused", "VPN is paused, waiting for network connection.");

5. Client Network List (CNL) Feature: If the Client Network List feature is used, you can provide a notification to inform users.

builder.inCnl("Network Feature", "Client Network List feature is active.");

Notification Message and Title Fallback

The SDK provides notifications to users during different VPN states (such as "connected" or "paused"). However, if you do not explicitly define custom notifications for these states, the SDK has a fallback process in place to ensure that meaningful information is still displayed to the user. This fallback process guarantees that the user is kept informed, even when you haven’t manually set up specific notifications.

By default, the SDK will always show notifications for the CONNECTED and PAUSED states, even if you do not configure them. The fallback process kicks in when specific customization is missing.

Here’s a step-by-step breakdown of how the SDK handles the fallback for notification messages and titles:

  1. If inConnected was not called

The SDK allows you to customize notifications for different VPN states using methods like inConnected(). For example, you can specify the title and message when the VPN is connected:

builder.inConnected("VPN Connected", "Your VPN is now connected.") 

What happens if you don’t call inConnected()?

If you don’t explicitly set a notification for the CONNECTED state using inConnected(), the SDK will try to fall back to a general title that is set in the NotificationConfig.Builder. This means that the SDK will search for any custom title provided in the configuration and use that instead.

  1. If No Custom Title is set using NotificationConfig.Builder.title()

If you haven’t called inConnected() and also haven’t set a custom title for notifications using NotificationConfig.Builder.title(), the SDK will move to the next fallback option: the app’s name.

The method builder.title() allows you to set a more generic title that can be used across multiple states (such as connected, paused, or disconnected). For example:

builder.title("VPN Status");

This generic title will be used for notifications unless specific messages are set for different VPN states.

What happens if you don’t set a title with builder.title() either?

If no title is provided with builder.title(), the SDK will then use the app’s name as defined in your AndroidManifest.xml file.

  1. If no title is set, the SDK uses the App Name from AndroidManifest.xml

At this stage, if neither inConnected() nor builder.title() was called, the SDK will use the name of your app as a fallback. This app name is the name that appears in the app launcher (on the user’s home screen) and is defined in the AndroidManifest.xml file.

Here’s where the app’s name is set in the manifest:

<application
    android:label="@string/app_name">
</application>

The android:label points to a string resource that contains the name of your app. This string is usually stored in a file called strings.xml in the res/values folder:

<resources>
    <string name="app_name">My VPN App</string>
</resources>

In this case, if no custom title or message is set, the notification title will simply show “My VPN App” (or any name you’ve defined) as the fallback title when the VPN is connected or paused.

  1. If No Custom Message Is Set, the SDK Uses Default String Resources

In addition to the title, the SDK can display default messages based on the VPN’s state. If you haven’t provided custom messages for these states (like connected or paused), the SDK will search for predefined string resources to use as the message.

For example:

If no message for the CONNECTED state is provided using inConnected(), the SDK will look for a default string resource called default_notification_connected_message.

Example of the default string resource in strings.xml:

<string name="default_notification_connected_message">VPN is connected</string>

Similarly, for the PAUSED state, if no message is provided using inPause(), the SDK will use a default string resource called default_notification_paused_message. Example:

<string name="default_notification_paused_message">VPN is paused</string>

Why is this fallback important?

Even if you don’t customize the messages, the SDK ensures that meaningful text is shown to users. This prevents the app from showing blank or empty notifications, ensuring a consistent user experience.

Fallback Flow Recap

Here’s the order in which the SDK decides what to show for the title and message in notifications:

  1. First priority: The title and message you explicitly set using methods like inConnected() and inPause() (for specific states).

  2. Second priority: A generic title you set using builder.title() (if state-specific titles aren’t provided).

  3. Third priority: The app’s name from the AndroidManifest.xml file is used as the title if no custom titles are set.

  4. Fourth priority: Default string resources like default_notification_connected_message and default_notification_paused_message are used for the message if no custom messages are set.

Summary

  • When the VPN is in a certain state (like connected or paused), the SDK shows notifications to keep the user informed.

  • If you don’t set a custom title and message for these notifications, the SDK will use a fallback process to ensure something meaningful is still displayed.

  • The fallback process goes from your custom notifications, to general titles, to the app name, and finally to default string resources. This ensures that users always see a notification, even if you haven’t explicitly set one.

This fallback mechanism is designed to prevent your app from showing incomplete or confusing notifications, ensuring a smooth user experience even when certain settings are not customized.

Notification Click Intent

clickAction Method

  • The clickAction method is used to specify what should happen when a user clicks on the notification that is generated by the VPN SDK. This is typically handled through Intents in Android.

  • Intents are used to trigger activities or services. If you don't define a clickAction, the SDK will default to opening the app’s main launch activity.

Intent Extras

  • The SDK will include a specific extra in the Intent when the notification is clicked. The extra is a boolean value with the key UnifiedSDKNotificationManager.EXTRA_NOTIFICATION, which is set to true.

  • Your activity can check for this extra to know that the user has clicked a VPN-related notification.

Activity Handling

  • To ensure that a specific Activity (which is the screen or part of the app that you want to display) is launched when the notification is clicked, you need to define an Intent Filter in the AndroidManifest.xml file.

  • The intent-filter helps the system recognize which activity to open when the notification is clicked. The <action> tag is where you define the custom action, and <category> is where you declare that this Intent belongs to the "default" category.

To handle the click action, register intent-filter with your activity:

<intent-filter>
    <action android:name="com.sdk.notification.action"/>
    <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

This means:

  • When the user clicks on the notification, the SDK will send an Intent with the action "com.sdk.notification.action".

  • Android will look for an activity that has registered to handle this action (through the intent-filter) and open that activity.

Updating Notification Preferences

Usage: You create a new configuration (e.g., what notifications should display), and then use the update() method to apply those changes immediately.

Notification config can be updated by calling the SDK method:

UnifiedSDK.update(createNotificationConfig());

Connected State Notification Placeholders

In the CONNECTED state, you can use placeholders in notifications to display real-time information about your VPN connection. These placeholders are special codes that will automatically update with live data while the VPN is connected.

Here are the available placeholders and what they do:

  • {dS} – Shows the current download speed. This tells the user how fast data is being downloaded while the VPN is on.

  • {uS} – Shows the current upload speed. This tells the user how fast data is being uploaded while the VPN is on.

  • {dT} – Shows the total amount of downloaded data. This tells the user how much data has been downloaded in total since the VPN connected.

  • {uT} – Shows the total amount of uploaded data. This tells the user how much data has been uploaded in total since the VPN connected.

Kotlin

val notificationConfig = SdkNotificationConfig.newBuilder() 
 .inConnected("VPN Connected", "Download Speed: {dS}, Upload Speed: {uS}") 
 .build()

 UnifiedSDK.update(notificationConfig)

Groovy

def notificationConfig = SdkNotificationConfig.newBuilder()
    .inConnected("VPN Connected", "Download Speed: {dS}, Upload Speed: {uS}")
    .build()

UnifiedSDK.update(notificationConfig)

In this example:

  • The title of the notification will be "VPN Connected".

  • The message will show the actual download and upload speeds, which will be updated automatically as the connection changes.

These placeholders give your users more useful information about their VPN connection without needing to open the app.

Disabling Notifications

If you prefer to completely disable notifications within your app, you can do so by calling the disabled() method on the SdkNotificationConfig.Builder. This can be useful if you are managing notifications in your own way or if notifications are not required for your specific use case.

To disable notifications:

SdkNotificationConfig.Builder builder = SdkNotificationConfig.newBuilder();
builder = builder.disabled()

Once disabled, no notifications related to VPN status will be shown to the user.

Analytics

SDK sends internal analytics events. They can be disabled by:

UnifiedSdk.setAnalyticsEnabled(false);
PreviousApplication SetupNextBackend URL Configuration

Last updated 5 months ago

Was this helpful?

If you cannot enable Java 8 or higher (up to Java 21) support in your project, please contact your account manager for assistance. If you do not have an account manager, please contact us .

Purpose: The UnifiedSDK.update(createNotificationConfig()) call allows you to update the notification settings for the SDK dynamically at runtime. The states were defined previously .

here
here