Mobile networks have the capability to establish multiple APNs simultaneously with the phones attached to the network.
When android applications on an Android phone need to communicate over the network, does the Android OS enable its applications to choose which APN will be used to carry their communications?
Please note that I am not asking how to change the default APN.
The use case is that there are one or more applications that require the use of specific APNs (for example to reach network resources not available through the default APN connection) but other applications (such as gmail, web browsing, youtube, Signal, etc) still need to be able to access the internet so the "default" APN needs to be simultaneously established when the "specific" APNs are in use (and viceversa).
Typically, if you want an APN, you'd ask for a network with TRANSPORT_CELLULAR. Now, you need to have a NetworkCapability on the particular APN that you can use to uniquely identify it. In this case, I am going to choose NET_CAPABILITY_NOT_RESTRICTED.
This particular capability is used to identify restricted networks that should not be chosen as the default network. Now, you are welcome to choose any NetworkCapability that you like. Keep in mind, NET_CAPABILITY_NOT_RESTRICTED is a restricted capability therefore you would need to have elevated permissions to request it.
Finally, assuming you have the first APN setup along with a second APN setup with NetworkCapabilities that make it unique, you can then update those apps to create a NetworkRequest which they can then use to uniquely request the second APN.
Therefore on the second APN, you would have to set it up with its unique NetworkCapability configuration. In our case, remove the NET_CAPABILITY_NOT_RESTRICTED which in turn makes it a restricted network. Now, you create a network request, but ask for TRANSPORT_CELLULAR and remove NET_CAPABILITY_NOT_RESTRICTED since this is included by default.
Here is an example demoing the above:
final NetworkRequest request =
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.build();
final ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkCallback networkCallback = new NetworkCallback() {
...
@Override
void onAvailable(...) {
// Triggers when this network is available so you can bind to it.
}
@Override
void onUnavailable(...) {
// Triggers when this network is lost.
}
...
};
connectivityManager.requestNetwork(request, networkCallback);
Assuming you have setup the second APN correctly, the above will allow an application to uniquely request it while other applications will continue to use the first APN.