2017-01-31 4 views
0

Wir arbeiten an der nativen Reaktion und haben NetInfo Event Listener implementiert, um die Internetkonnektivität zu überprüfen.Wenn die App im Hintergrund ist und die Internetverbindung verloren gegangen ist, wird die App abgestürzt

Wir rufen auch fetch() bei Ereignissen auf, um Daten von Google API zu erhalten. Wenn App ist im Hintergrund und wenn Internet-Verbindung verloren dann app mit folgendem Fehler abgestürzt immer:

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: [email protected]:21 
E AndroidRuntime: [email protected]:19 
E AndroidRuntime: [email protected]:19 
E AndroidRuntime: [email protected]:19 
E AndroidRuntime: <unknown>@27764:57 
E AndroidRuntime: [email protected]:28 
E AndroidRuntime: [email protected]:39 
E AndroidRuntime: <unknown>@7443:21 
E AndroidRuntime: [email protected]:3 
E AndroidRuntime: [email protected]: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$3.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 

Ich habe erstellt Android nativen Modul reagiert GPS aktuellen Standort mit NETWORK_PROVIDER zu bekommen.

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..."); 
    } 
} 
} 

Ich rufe dieses Modul in componentDidMount() in folgender Weise:

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

Ereignis-Listener für Standortaktualisierungen

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

Listener Funktion

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)=>{ 
        ... 
       }); 
     } 
     } 
    } 
    } 

Jeder Vorschlag geschätzt.

+0

Haben Sie versucht, try-catch-Anweisungen zu verwenden, um die Fehler abzufangen und weiterzugehen? – Enfyve

+0

Hi Enfyve, ja, ich habe diesen Code in try-catch-Anweisungen eingepackt, aber es geht nicht, wenn die App in der Hintergrund-App ist. Ich versuchte auch AppState zu verwenden, um zu überprüfen, ob App im Hintergrund ist, dann kehrte ich in OnLocationChange-Funktion zurück, so dass fetch() nicht ausgeführt wird, aber es immer noch abstürzte. –

+0

Anstatt das dann tun holen Prüfen, ob Verbindung info! = 'NONE', warum nicht 'NetInfo.isConnected.fetch(). Fertig (...' – Enfyve

Antwort

0

Ich habe die Ursache des Problems gefunden. Es geschah wegen fetch(). Wenn Sie fetch() verwenden und die Internetverbindung verloren ist, während die App im Hintergrund läuft, schlägt die Methode fetch() aufgrund eines Netzwerkfehlers fehl.

Ich habe catch() in fetch() hinzugefügt, um netzwerkbezogene Fehler zu behandeln. Unten ist Syntax.

 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 
    }); 
Verwandte Themen