diff options
author | Sho Amano <samano@xevo.com> | 2018-10-11 22:15:06 +0900 |
---|---|---|
committer | Sho Amano <samano@xevo.com> | 2018-10-12 21:20:35 +0900 |
commit | f362309c3c9532a46a972c64640dd366f2b6c6a3 (patch) | |
tree | 468ce672e420ea360319ba5dba4597efc6908437 | |
parent | 44c3f2ab669e047101f212d5258983043299716f (diff) | |
download | sdl_android-f362309c3c9532a46a972c64640dd366f2b6c6a3.tar.gz |
Reflect review comments
- Check ACCESS_NETWORK_STATE permission to avoid crash
- Create a normal Socket when Wi-Fi network isn't
available or the permission isn't available
- Add null checkings
-rw-r--r-- | sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java b/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java index 31449cf57..b35070d89 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java +++ b/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java @@ -1,7 +1,9 @@ package com.smartdevicelink.transport.utl; +import android.Manifest; import android.annotation.TargetApi; import android.content.Context; +import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; @@ -10,53 +12,85 @@ import android.os.Build; import java.io.IOException; import java.net.Socket; +import javax.net.SocketFactory; + import static com.smartdevicelink.util.NativeLogTool.logInfo; public class WiFiSocketFactory { /** - * Creates a TCP socket which is bound to Wi-Fi network (for Android 5+) + * Try to create a TCP socket which is bound to Wi-Fi network (for Android 5+) * - * On Android 5 and later, this method returns a Socket which is always bound to a Wi-Fi - * network. If the phone is not connected to a Wi-Fi network, this method throws an IOException. - * Prior to Android 5, this method simply creates a Socket equivalent to "new Socket();". + * On Android 5 and later, this method tries to create a Socket instance which is bound to a + * Wi-Fi network. If the phone is not connected to a Wi-Fi network, or the app lacks + * required permission (ACCESS_NETWORK_STATE), then this method simply creates a Socket instance + * with "new Socket();". * - * @return a Socket instance bound to Wi-Fi network. + * @return a Socket instance, preferably bound to a Wi-Fi network */ - public static Socket createSocket(Context context) throws IOException { + public static Socket createSocket(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Socket socket = createWiFiSocket(context); - if (socket == null) { - logInfo("Cannot find Wi-Fi network, aborting socket creation."); - throw new IOException("The phone is not connected to Wi-Fi network"); + if (socket != null) { + logInfo("Created a Socket bound to Wi-Fi network"); + return socket; } - return socket; - } else { - return new Socket(); } + + return new Socket(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static Socket createWiFiSocket(Context context) { + PackageManager pm = context.getPackageManager(); + if (pm == null) { + logInfo("PackageManager isn't available."); + return null; + } + // getAllNetworks() and getNetworkCapabilities() require ACCESS_NETWORK_STATE + if (pm.checkPermission(Manifest.permission.ACCESS_NETWORK_STATE, context.getPackageName()) != PackageManager.PERMISSION_GRANTED) { + logInfo("Router service doesn't have ACCESS_NETWORK_STATE permission. It cannot bind a TCP transport to Wi-Fi network."); + return null; + } + ConnectivityManager connMan = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); - // requires ACCESS_NETWORK_STATE permission + if (connMan == null) { + logInfo("ConnectivityManager isn't available."); + return null; + } + Network[] allNetworks = connMan.getAllNetworks(); + if (allNetworks == null) { + logInfo("Failed to acquire a list of networks."); + return null; + } // Samsung Galaxy S9 (with Android 8.0.0) provides two `Network` instances which have // TRANSPORT_WIFI capability. The first one throws an IOException upon creating a Socket, // and the second one actually works. To support such case, here we iterate over all // `Network` instances until we can create a Socket. for (Network network : allNetworks) { - // requires ACCESS_NETWORK_STATE permission + if (network == null) { + continue; + } + NetworkCapabilities capabilities = connMan.getNetworkCapabilities(network); + if (capabilities == null) { + continue; + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { try { - return network.getSocketFactory().createSocket(); + SocketFactory factory = network.getSocketFactory(); + if (factory != null) { + return factory.createSocket(); + } } catch (IOException e) { logInfo("IOException during socket creation (ignored): " + e.getMessage()); } } } + logInfo("Cannot find Wi-Fi network to bind a TCP transport."); return null; } } |