当应用程序处于后台并且互联网连接丢失时,应用程序会崩溃

when app is in background and if internet connection lost, app is getting crashed

我们正在研究 React Native,我们实现了 NetInfo 事件侦听器来检查互联网连接。

我们还在事件上调用 fetch() 以从 google api 获取数据。当应用程序处于后台并且互联网连接丢失时,应用程序会崩溃并出现以下错误:

ReactNativeJS: Network request failed
E AndroidRuntime: FATAL EXCEPTION: mqt_native_modules
E AndroidRuntime: Process: com.example, PID: 30344
E AndroidRuntime: com.facebook.react.common.JavascriptException: Network request failed, stack:
E AndroidRuntime: onerror@25623:21
E AndroidRuntime: dispatchEvent@10670:19
E AndroidRuntime: setReadyState@27824:19
E AndroidRuntime: __didCompleteResponse@27660:19
E AndroidRuntime: <unknown>@27764:57
E AndroidRuntime: emit@9771:28
E AndroidRuntime: __callFunction@7571:39
E AndroidRuntime: <unknown>@7443:21
E AndroidRuntime: guard@7381:3
E AndroidRuntime: callFunctionReturnFlushedQueue@7442:6
E AndroidRuntime:
E AndroidRuntime: at com.facebook.react.modules.core.ExceptionsManagerModule.showOrThrowError(ExceptionsManagerModule.java:97)
E AndroidRuntime: at com.facebook.react.modules.core.ExceptionsManagerModule.reportFatalException(ExceptionsManagerModule.java:81)
E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
E AndroidRuntime:        at com.facebook.react.bridge.BaseJavaModule$JavaMethod.invoke(BaseJavaModule.java:318)
E AndroidRuntime:        at com.facebook.react.cxxbridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:158)
E AndroidRuntime:        at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
E AndroidRuntime:        at android.os.Handler.handleCallback(Handler.java:739)
E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:95)
E AndroidRuntime:        at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31)
E AndroidRuntime:        at android.os.Looper.loop(Looper.java:148)
E AndroidRuntime:        at com.facebook.react.bridge.queue.MessageQueueThreadImpl.run(MessageQueueThreadImpl.java:196)
E AndroidRuntime:        at java.lang.Thread.run(Thread.java:818)
I ReactNativeJS: auth/network-request-failed
I ReactNativeJS: A network error (such as timeout, interrupted connection or unreachable host) has occurred.
W ActivityManager:   Force finishing activity com.example/.MainActivity

我创建了 android 反应本机模块以使用 NETWORK_PROVIDER 获取 GPS 当前位置。

public class GpsLocationCheckModule extends ReactContextBaseJavaModule implements LocationListener{
private Promise promiseCallback;
public boolean gps_enabled = false;
private ReactApplicationContext mReactContext;
private Activity currentActivity;
private static final String SETTINGS_FAILURE = "SETTINGS_FAILURE";
private LocationManager locationManager;
public static final String TAG = GpsLocationCheckModule.class.getSimpleName();
private String messageText;
private Location location;
private boolean isPopUpDisplayed = false;

public GpsLocationCheckModule(ReactApplicationContext reactContext) {
    super(reactContext);
    //reactContext.addActivityEventListener(mActivityEventListener);
    mReactContext = reactContext;
   reactContext.addActivityEventListener(mActivityEventListener);        
}

@Override
public String getName() {
    return "GpsServiceLocation"; //this will be use at JS side.
}

@ReactMethod
public void checkLocation(String message, Promise promise) { 
    currentActivity = getCurrentActivity();
    promiseCallback=promise;
    messageText= message;
    Log.i(TAG,"check location");
    locationManager = (LocationManager)mReactContext.getSystemService(Context.LOCATION_SERVICE);
    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0, 0, this);        
    boolean gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    if(!gps_enabled){
        if(!isPopUpDisplayed){
            isPopUpDisplayed = true;
            Log.i(TAG,"checklocatoin disabled" + Boolean.toString(isPopUpDisplayed));
            displayPromptForEnablingGPS(currentActivity,messageText,promiseCallback);
        }            
    }       
}

@Override
public void onLocationChanged(Location location) {
    Log.i(TAG,"location changed");
    String msg = "New Latitude: " + location.getLatitude()
            + "New Longitude: " + location.getLongitude();
    Log.i(TAG,msg);
    WritableMap params = Arguments.createMap();
    params.putDouble("Longitude", location.getLongitude());
    params.putDouble("Latitude", location.getLatitude());
    //locationManager.removeUpdates(this);
     Log.i(TAG,"removed");
   sendEvent(mReactContext, "locationChanged", params);
}

@Override
public void onProviderDisabled(String provider) {
    Log.i(TAG,"disabled");
    Log.i(TAG,"ispopup disabled" + Boolean.toString(isPopUpDisplayed));
    if(!isPopUpDisplayed){
        isPopUpDisplayed = true;
        Log.i(TAG,"ispopup inside disabled" + Boolean.toString(isPopUpDisplayed));
        displayPromptForEnablingGPS(currentActivity,messageText,promiseCallback);
    } 
}

@Override
public void onProviderEnabled(String provider) {
    Log.i(TAG,"enabled");
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
    Log.i(TAG,"status changed");
    // TODO Auto-generated method stub

}

private void displayPromptForEnablingGPS(final Activity activity, final String message, final Promise promise) {
    final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    final String action = android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS;

    builder.setMessage(Html.fromHtml(message))
            .setCancelable(false)
            .setPositiveButton("Yes",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogInterface, int id) {
                            activity.startActivityForResult(new Intent(action), 1);                                        
                            dialogInterface.dismiss();
                        }
                    })
            .setNegativeButton("No",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogInterface, int id) { 
                            popupRejected();                               
                            dialogInterface.cancel();
                        }
                    });
    builder.create().show();
}

private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
        currentActivity = activity;
        checkLocationService(true); 
    }
};

public void checkLocationService(Boolean status){
    WritableMap map = Arguments.createMap();
    map.putString("status", "success");  
    isPopUpDisplayed=false;
    Log.i(TAG,"ispopup checklocation" + Boolean.toString(isPopUpDisplayed));
    if(promiseCallback != null){
        promiseCallback.resolve(map);
        promiseCallback = null;
    }            
}
public void popupRejected(){
    isPopUpDisplayed = false;
    Log.i(TAG,"ispopup rejected" + Boolean.toString(isPopUpDisplayed));
    if(promiseCallback != null){                               
        promiseCallback.reject(SETTINGS_FAILURE,"Gps enabling failed");
    }
}

 /*
 * Internal function for communicating with JS
 */
private void sendEvent(ReactContext reactContext, 
    String eventName, @Nullable WritableMap params) {
    if (reactContext.hasActiveCatalystInstance()) {
        reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, params);
    } else {
        Log.i(TAG, "Waiting for CatalystInstance...");
    }
}   
}

我通过以下方式在 componentDidMount() 中调用此模块:

componentDidMount() {
     NetInfo.addEventListener(
        'change',
        this._handleConnectionInfoChange
    );   
    NetInfo.fetch().done(
       (connectionInfo) => { this.setState({connectionInfo}); }
    );  
    GpsServiceLocation.checkLocation(this.state.message).catch((error)=>{});
    }

位置更新的事件侦听器

constructor(props) {
      if (!this.evEmitter) {
      // Register Listener Callback - has to be removed later
       this.evEmitter = DeviceEventEmitter.addListener('locationChanged', this.onLocationChange.bind(this));      
    }  
   }

监听函数

onLocationChange (e: Event) { 
         NetInfo.fetch().done(
       (connectionInfo) => { 

  if(connectionInfo != 'NONE'){     
    if(e.Latitude != 0 && e.Longitude != 0){ 
             fetch('https://maps.googleapis.com/maps/api/distancematrix/json?origins='+e.Latitude+','+e.Longitude+'&destinations='+destLatlng+'&mode=walking&key=<key>')
                .then((responseData) => responseData.json())
                .done((responseData)=>{
                     ...
                });
         }
      }
   }
   }

任何建议表示赞赏。

我找到了问题的原因。这是由于 fetch() 而发生的。如果您正在使用 fetch() 并且当应用程序在后台时互联网连接丢失,则 fetch() 方法因网络错误而失败。

我在 fetch() 中添加了 catch() 来处理与网络相关的错误。以下是语法。

     fetch('https://maps.googleapis.com/maps/api/distancematrix/json?origins='+e.Latitude+','+e.Longitude+'&destinations='+destLatlng+'&mode=walking&key=<key>')
            .then((responseData) => responseData.json())
            .done((responseData)=>{
                 ...
     }).catch((error)=>{
         //handle your error here
     });