Migration Guide From v1.1.0

Oneconnect Android SDK Migration Guide

From v1.1.0 🠒 v1.1.71

This section highlights updates to the OneConnect SDK, replacing deprecated patterns with modern implementations. It explains how to migrate from legacy server fetching and broadcast handling to the new, recommended APIs, ensuring compatibility with Android 13+ and providing cleaner, more reliable integration flows.


📋Changes to AndroidManifest.xml

Additional required permissions:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

⚠️ Google Play Policy Note: If you publish your app, you must justify the use of FOREGROUND_SERVICE by submitting a video showing your app running in the background with notifications enabled.

Component Declarations Changes

Old declaration:

<activity
    android:name="top.oneconnectapi.app.DisconnectVPNActivity"
    android:excludeFromRecents="true"
    android:noHistory="true"
    android:taskAffinity=".DisconnectVPN"
    android:theme="@style/blinkt.dialog" />
<service
    android:name="top.oneconnectapi.app.core.OpenVPNService"
    android:permission="android.permission.BIND_VPN_SERVICE"
    android:exported="true">
    <intent-filter>
        <action android:name="android.net.VpnService" />
    </intent-filter>
</service>

New declaration:

<activity
    android:name="top.oneconnectapi.app.activities.DisconnectVPN"
    android:autoRemoveFromRecents="true"
    android:excludeFromRecents="true"
    android:noHistory="true"
    android:taskAffinity=".DisconnectVPN"
    android:theme="@style/blinkt.dialog" />

<service
    android:name="top.oneconnectapi.app.core.OpenVPNService"
    android:exported="true"
    android:permission="android.permission.BIND_VPN_SERVICE"
    android:foregroundServiceType="specialUse"
    android:process=":openvpn">
    <intent-filter>
        <action android:name="android.net.VpnService" />
    </intent-filter>
    <property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="vpn"/>
</service>

<service
    android:name="top.oneconnectapi.app.core.keepVPNAlive"
    android:process=":openvpn"
    android:exported="true"
    android:permission="android.permission.BIND_JOB_SERVICE"/>

🚀 Server Fetching Changes

Old Implementation:

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            OneConnect oneConnect = new OneConnect();
            String apiKey = "nwc6VcLemvnZQxaAgmMGMLtLMxmNT7tud.X.WXBqFbXjWogVWk"; //Sample API key
            oneConnect.initialize(this, apiKey);
            try {
                //Returns a Json string containing all the server details and credentials
                Constants.FREE_SERVERS = oneConnect.fetch(true);
                Constants.PREMIUM_SERVERS = oneConnect.fetch(false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

thread.start();

New Implementation:

OneConnect oneConnect = new OneConnect();
oneConnect.initialize(this, "nwc6VcLemvnZQxaAgmMGMLtLMxmNT7tud.X.WXBqFbXjWogVWk"); //Sample API key

oneConnect.fetchJson(new JsonResponseListener() {
    @Override
    public void onSuccess(String freeServersJson, String premiumServersJson) {
        Constants.FREE_SERVERS = oneConnect.fetch(true);
        Constants.PREMIUM_SERVERS = oneConnect.fetch(false);
    }

    @Override
    public void onFailure(Exception e) {
        Log.e("OneConnectServer", "Failed to fetch servers", e);
    }
});

Instead of fetching raw JSON and parsing it manually, use the typed response listener. This returns lists of free and premium OneConnectServer objects directly. Here is a sample code.

OneConnect oneConnect = new OneConnect();
oneConnect.initialize(this, "nwc6VcLemvnZQxaAgmMGMLtLMxmNT7tud.X.WXBqFbXjWogVWk"); //Sample API key

oneConnect.fetch(new ServerResponseListener() {
    @Override
    public void onSuccess(ArrayList<OneConnectServer> freeServersList, ArrayList<OneConnectServer> premiumServersList) {
        // Print the first free server details to Logcat
        Log.d("OneConnectServer",
                "ID: " + freeServersList.get(0).getId() +
                ", Name: " + freeServersList.get(0).getServerName() +
                ", Country: " + freeServersList.get(0).getCountry() +
                ", Username: " + freeServersList.get(0).getVpnUserName() +
                ", Configuration: " + freeServersList.get(0).getOvpnConfiguration());
    }

    @Override
    public void onFailure(Exception e) {
        Log.e("OneConnectServer", "Failed to fetch servers", e);
    }
});

🛑 Stopping VPN

Old implementation:

OpenVPNThread vpnThread = new OpenVPNThread();

try {
    vpnThread.stop();
} catch (Exception e) {
    e.printStackTrace();
}

New implementation:

Intent intent = new Intent(getContext(), DisconnectVPN.class);
intent.putExtra("instantStop", true); //Pass this to stop vpn without alert dialog
startActivity(intent);

You no longer need to create an instance of OpenVPNThread. Instead, just launch the DisconnectVPN activity included in the SDK. By default, this will not open a new screen but instead display an alert dialog asking for confirmation. You can bypass the dialog and stop the connection immediately by passing the instantStop flag.


📡 Registering Receiver

Old implementation:

LocalBroadcastManager.getInstance(this)
                .registerReceiver(broadcastReceiver, IntentFilter("connectionState"))

New implementation:

IntentFilter filter = new IntentFilter("top.oneconnectapi.app.VPN_STATS");

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    registerReceiver(broadcastReceiver, filter, Context.RECEIVER_EXPORTED);
} else {
    registerReceiver(broadcastReceiver, filter);
}

LocalBroadcastManager is deprecated. We now use registerReceiver with a namespaced action (top.oneconnectapi.app.VPN_STATS) to align with Android’s modern broadcast handling and ensure compatibility with Android 13+ requirements. Don't forget to unregister the receiver when you no longer need it.


Last updated