2017-01-31 10 views
0

ネイティブの反応に取り組んでおり、インターネット接続をチェックするためにNetInfoイベントリスナーを実装しました。アプリがバックグラウンドでインターネット接続が失われた場合、アプリがクラッシュする

また、Google apiからデータを取得するために、イベントに対してfetch()を呼び出しています。アプリがバックグラウンドであり、インターネット接続が失わあればアプリは次のエラーでクラッシュしたばかりのとき:

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 

私はアンドロイドの作成した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)=>{ 
        ... 
       }); 
     } 
     } 
    } 
    } 

任意の提案を感謝。

+0

try-catchステートメントを使用してエラーをトラップして移動しようとしましたか? – Enfyve

+0

こんにちはEnfyve、はい私はtry-catchステートメントでそのコードをラップしましたが、アプリケーションがバックグラウンドアプリにあるときは処理しません。私はまたAppStateを使ってアプリケーションがバックグラウンドにあるかどうかをチェックしてから、OnLocationChange関数に戻ってきてfetch()が実行されないようにしましたが、まだクラッシュしていました。 –

+0

「NetInfo.isConnected.fetch()。done(... ')」というメッセージが表示されます。 – Enfyve

答えて

0

問題の原因が見つかりました。 fetch()のために起こっていました。 fetch()を使用していて、バックグラウンドでapp中にインターネット接続が失われた場合、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 
    }); 
関連する問題