From f168fc335e8a120c8bb4c8e31398c6241e0c4f74 Mon Sep 17 00:00:00 2001 From: Martin Konicek Date: Fri, 11 Dec 2015 10:22:37 -0800 Subject: [PATCH] Don't insta-crash when network permission is missing Summary: public Rename the `ConnectivityModule` to `NetInfoModule` (there's no need to name things differently in two places). Add exception handling to the module in case the network permission is missing. When the permission is missing, throw an actionable error from all calls to `NetInfo`: http://imgur.com/zVIMxOV Without this change, the app immediately crashes on startup: `getCurrentConnectionType` is called from `Activity.onResume`. Reviewed By: andreicoman11, bestander Differential Revision: D2749230 fb-gh-sync-id: 1b752d21a8f28ffeaf60a3322cb76f869dc70a14 --- ...ectivityModule.java => NetInfoModule.java} | 49 +++++++++++++++---- .../react/shell/MainReactPackage.java | 4 +- 2 files changed, 42 insertions(+), 11 deletions(-) rename ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/{ConnectivityModule.java => NetInfoModule.java} (71%) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/ConnectivityModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java similarity index 71% rename from ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/ConnectivityModule.java rename to ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java index acf6060b1..bff80bf26 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/ConnectivityModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java @@ -1,4 +1,11 @@ -// Copyright 2004-present Facebook. All Rights Reserved. +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ package com.facebook.react.modules.netinfo; @@ -10,6 +17,7 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.support.v4.net.ConnectivityManagerCompat; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; @@ -17,25 +25,30 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.common.ReactConstants; import static com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter; /** * Module that monitors and provides information about the connectivity state of the device. */ -public class ConnectivityModule extends ReactContextBaseJavaModule +public class NetInfoModule extends ReactContextBaseJavaModule implements LifecycleEventListener { private static final String CONNECTION_TYPE_NONE = "NONE"; private static final String CONNECTION_TYPE_UNKNOWN = "UNKNOWN"; + private static final String MISSING_PERMISSION_MESSAGE = + "To use NetInfo on Android, add the following to your AndroidManifest.xml:\n" + + ""; private final ConnectivityManager mConnectivityManager; private final ConnectivityManagerCompat mConnectivityManagerCompat; private final ConnectivityBroadcastReceiver mConnectivityBroadcastReceiver; + private boolean mNoNetworkPermission = false; private String mConnectivity = ""; - public ConnectivityModule(ReactApplicationContext reactContext) { + public NetInfoModule(ReactApplicationContext reactContext) { super(reactContext); mConnectivityManager = (ConnectivityManager) reactContext.getSystemService(Context.CONNECTIVITY_SERVICE); @@ -69,11 +82,23 @@ public class ConnectivityModule extends ReactContextBaseJavaModule @ReactMethod public void getCurrentConnectivity(Callback successCallback, Callback errorCallback) { + if (mNoNetworkPermission) { + if (errorCallback == null) { + FLog.e(ReactConstants.TAG, MISSING_PERMISSION_MESSAGE); + return; + } + errorCallback.invoke(MISSING_PERMISSION_MESSAGE); + return; + } successCallback.invoke(createConnectivityEventMap()); } @ReactMethod public void isConnectionMetered(Callback successCallback) { + if (mNoNetworkPermission) { + FLog.e(ReactConstants.TAG, MISSING_PERMISSION_MESSAGE); + return; + } successCallback.invoke(mConnectivityManagerCompat.isActiveNetworkMetered(mConnectivityManager)); } @@ -98,15 +123,21 @@ public class ConnectivityModule extends ReactContextBaseJavaModule } private String getCurrentConnectionType() { - NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo(); - if (networkInfo == null || !networkInfo.isConnected()) { - return CONNECTION_TYPE_NONE; - } else if (ConnectivityManager.isNetworkTypeValid(networkInfo.getType())) { - return networkInfo.getTypeName().toUpperCase(); - } else { + try { + NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo(); + if (networkInfo == null || !networkInfo.isConnected()) { + return CONNECTION_TYPE_NONE; + } else if (ConnectivityManager.isNetworkTypeValid(networkInfo.getType())) { + return networkInfo.getTypeName().toUpperCase(); + } else { + return CONNECTION_TYPE_UNKNOWN; + } + } catch (SecurityException e) { + mNoNetworkPermission = true; return CONNECTION_TYPE_UNKNOWN; } } + private void sendConnectivityChangedEvent() { getReactApplicationContext().getJSModule(RCTDeviceEventEmitter.class) .emit("networkStatusDidChange", createConnectivityEventMap()); diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java index 973cfbd84..d6d8e37fb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java @@ -20,7 +20,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.modules.fresco.FrescoModule; import com.facebook.react.modules.intent.IntentModule; import com.facebook.react.modules.location.LocationModule; -import com.facebook.react.modules.netinfo.ConnectivityModule; +import com.facebook.react.modules.netinfo.NetInfoModule; import com.facebook.react.modules.network.NetworkingModule; import com.facebook.react.modules.storage.AsyncStorageModule; import com.facebook.react.modules.toast.ToastModule; @@ -57,7 +57,7 @@ public class MainReactPackage implements ReactPackage { new IntentModule(reactContext), new LocationModule(reactContext), new NetworkingModule(reactContext), - new ConnectivityModule(reactContext), + new NetInfoModule(reactContext), new WebSocketModule(reactContext), new ToastModule(reactContext)); }