2

我試圖找出Google Play服務爲什麼會在應用程序從諸如設備睡眠或切換其他程序的背景狀態返回後發生nullpointerexception崩潰。有時Google Play服務會在應用程序啓動時提供崩潰彈出窗口。所以我認爲問題在於服務路徑上的某處,因爲rxjava是線程發生的地方。GoogleApiClient不能爲空[Awareness API]

Note: I Inject GoogleApiClient in both MainActivity (field injection) and in GoogleApiService (constructor injection). 

GoogleApiClient是作爲@Singleton注入的。我一直在試圖追蹤爲什麼這會發生幾個小時而沒有進展,任何幫助表示讚賞。

應用程序將繼續沒有任何問題需要解決,「谷歌遊戲服務彈出」很討厭,雖然,我看到一個調用getuserLocAndWeather()的返回失去連接到Google Play服務,但它立刻返回一個有效的結果下一個電話。

MainActivity和GoogleApiService中的實際對象引用永遠不爲null,引用始終是相同的,例如[email protected],並且在調用時始終連接。

跟蹤:

FATAL EXCEPTION: lowpool[3] 
Process: com.google.android.gms.persistent, PID: 12828 
java.lang.NullPointerException: GoogleApiClient must not be null 
    at ilk.a(:com.google.android.gms:73) 
    at hys.<init>(:com.google.android.gms:115) 
    at pof.<init>(:com.google.android.gms:86) 
    at ppz.<init>(:com.google.android.gms:35) 
    at ppx.<init>(:com.google.android.gms:179) 
    at ppp.a(:com.google.android.gms:179) 
    at buc.a(:com.google.android.gms:381) 
    at jfo.run(:com.google.android.gms:1087) 
    at itt.run(:com.google.android.gms:453) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
    at iyg.run(:com.google.android.gms:17) 
    at java.lang.Thread.run(Thread.java:818) 

我的服務等級:,在try {}客戶端打印出來永遠是:true,如果谷歌無關發揮服務崩潰與否。

客戶端:[email protected]已連接? :真

public class GoogleApiService implements IGoogleApi{ 
private GoogleApiClient client; 
private static final String TAG = "GoogleApiClient"; 

@Inject 
public GoogleApiService(GoogleApiClient client){ 
    this.client = client; 

} 


public Observable<UserCurrentInfo> getLocationWeather(){ 
    Observable<WeatherResult> weatherObservable = Observable.create(subscriber -> { 

     try { 
      Log.d(TAG,"Trying to get some Weather"); 
      Log.d(TAG,"Client: " + client.toString() + " Connected? :" + client.isConnected()); 


      Awareness.SnapshotApi.getWeather(client) 
        .setResultCallback(weather -> { 
         if (!weather.getStatus().isSuccess()) { 
          subscriber.onError(new Throwable("could not get weather")); 
          Log.d(TAG," Error getting weather" + weather.getStatus().toString()); 

         } else { 
          Log.d(TAG,"Getting dem weathers"); 
          subscriber.onNext(weather); 
          subscriber.onCompleted(); 
         } 
        }); 
     }catch (SecurityException e){ 
      throw new SecurityException("No permission: " + e); 

     } 
    }); 



    Observable<LocationResult> locationObservable = Observable.create(subscriber -> { 
     try { 
      Awareness.SnapshotApi.getLocation(client) 
        .setResultCallback(retrievedLocation -> { 
         if (!retrievedLocation.getStatus().isSuccess()) { 
          subscriber.onError(new Throwable("Could not get location.")); 
          Log.d(TAG," Error getting location"); 

         } else { 
          subscriber.onNext(retrievedLocation); 
          subscriber.onCompleted(); 
         } 
        }); 
     }catch (SecurityException e){ 
      throw new SecurityException("No permission: " + e); 

     } 
    }); 

    return Observable.zip(weatherObservable, locationObservable, 
      (weather, location) -> { 
       return new UserCurrentInfo(weather.getWeather(),location.getLocation()); 
      }); 
} 

主持人:

public class FavouritesPresenter implements BasePresenter<IFavouriteView>{ 

private IFavouriteView favView; 
private String TAG = "FavPresenter"; 
private Subscription subscription; 
private GetUserLocationWeatherUseCase useCase; 

@Inject 
FavouritesPresenter(GetUserLocationWeatherUseCase wlUseCase){ 
    this.useCase = wlUseCase; 
} 
@Override 
public void onCreate() { 
} 

@Override 
public void onStop(){ 
    if(subscription != null){ 
     subscription.unsubscribe(); 
    } 
} 
public void getUserLocAndWeather(){ 
    subscription = useCase.execute().subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(info -> { 
         favView.showText(
           formatStringDecimals(info.getWeather().getTemperature(Weather.CELSIUS)+"",2), 
           info.getWeather().getConditions()[0], 
           formatStringDecimals(""+info.getLocation().getLatitude(),3), 
           formatStringDecimals("" + info.getLocation().getLongitude(),3) 

         );}, 
        err ->{favView.showText("??",0,"","");} 
      ); 
} 

用例:在mainactivity

public class GetUserLocationWeatherUseCase implements Usecase<UserCurrentInfo> { 
IGoogleApi apihelper; 

public GetUserLocationWeatherUseCase(IGoogleApi helper){ 
    this.apihelper = helper; 
} 
@Override 
public Observable<UserCurrentInfo> execute(){ 
    return apihelper.getLocationWeather(); 

} 

用法:

@Inject 
FavouritesPresenter favouritesPresenter; 
GoogleApiClient.ConnectionCallbacks connectionCallbacks; 
GoogleApiClient.OnConnectionFailedListener connectionFailedListener; 
@Inject 
GoogleApiClient mGoogleApiClient; 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    ButterKnife.bind(this); 
    initInjector(); 
    favouritesPresenter.attachView(this); 
    favouritesPresenter.onCreate(); 
    registerReceiverGPS(); 
} 



@Override 
protected void onStart() { 
    super.onStart(); 
    if (mGoogleApiClient != null){ 
     registerCallbacks(this.mGoogleApiClient); 
     registerFailedToConnect(this.mGoogleApiClient); 
     mGoogleApiClient.connect(); 
    } 
} 

@Override 
protected void onStop() { 
    favouritesPresenter.onStop(); 
    if (mGoogleApiClient != null) { 
     mGoogleApiClient.unregisterConnectionCallbacks(this.connectionCallbacks); 
     mGoogleApiClient.unregisterConnectionFailedListener(this.connectionFailedListener); 
     mGoogleApiClient.disconnect(); 
    } 
} 

@Override 
public void registerCallbacks(GoogleApiClient client){ 
    this.connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() { 
     @Override 
     public void onConnected(@Nullable Bundle bundle) 
      favouritesPresenter.getUserLocAndWeather(); //Call to presenter that initiates the observable chain, actually this    comes later after some GPS checks and such, but for easier cohesion 
     } 
     @Override 
     public void onConnectionSuspended(int i) {} 
    }; 
    client.registerConnectionCallbacks(this.connectionCallbacks); 
} 
+0

什麼,如果你對你的onCreate() 添加此如果(GoogleApiClient == NULL){ GoogleApiClient =新GoogleApiClient.Builder(本) .addConnectionCallbacks(本) .addOnConnectionFailedListener(本) .addApi(LocationServices .API) .build(); } –

+0

@Tony這已經發生在注入器中,對象本身從來沒有從我看到的實際上是空的,它總是有相同的引用MainActivity和GoogleApiService – buddhabath

+0

什麼時候程序崩潰? –

回答

1

在你在onStart()方法只能連接googleApiClient的對象,其餘的事情我在onCreate()方法中實現。

1

我想要做的第一件事是在onStart()到onResume()中的部分是move,以確保它們在用戶需要時存在,因爲這是在顯示App之前調用的最後一個方法。 onStop()與onPause()一樣。但不知何故,這似乎是一個太簡單的答案。

+0

是的,它在onResume()開始之前,我開始移動它,看看爲什麼它的行爲,但我只是嘗試綁定到一個按鈕的調用,而不是在onResume()運行它,看看是否解決了這個問題。 – buddhabath

+0

將異步調用綁定到一個按鈕是_always_一個好主意IMO;如果這變成年解決方案,buddhabath,考慮放棄其他線程viewDetach。善於使用DI;愛它。 –

1

我認爲Awareness.SnapshotApi.getWeather(client)可能是您的代碼開始呼叫com.google.android.gms:73的地方,因此將NPE添加到您的catch語句中可能是值得的,特別是因爲它是間歇性的。

&現在對其他人的說明:我只有建議這是因爲我看到他們使用rxJava與一些技能;看看GoogleApiClient中兩個monad聲明的簡潔性!他們所需要做的只是一個retryWhen(Func2<Integer, Throwable, Boolean>),並且在給定的throwable instanceof NPE和1的計數,也許是2的情況下,評估所述功能參數中的謂詞是真的。在壓縮之前,我認爲記錄和釋放進一步的NPE - 使得進一步的異常行爲顯而易見 - 可能滿足堅定的,受過教育的聲音,告訴我們永遠不要抓住NPE。 ...或者,如果這些調整公司的鼻子,受過教育的聲音聽起來是一個好時機,他們可以通過類型過濾了進一步的例外,同時提供相應的下游reactions這個預測事件......

hmmmmm Kermit Sipping Tea

我正要說你可以這樣做,因爲在monad create()方法中沒有一堆代碼,希望它可能成爲副作用的一部分;然而@buddhabath,我注意到那些create() s可以產生你所描述的訂閱副作用 - 在訂閱線程上,實際上是:

你應該是catching whatever comes out of those trys並將它發送到rxChooChoo;現存onError不應該是一個問題B/C只有一個將被稱爲每次評估。 只需將subscriber.onError()中的catch參數指向任何Throwable-excepting these Exceptions將保留在軌道中,可能就像我在Kermit上面描述的軌道一樣,但泄漏create()是您的錯誤。

tl; dr:手工定義monads與create()值得我們充分注意;這是真實的世界,非常「必要」;字面上任何事情都可能發生在那裏。我自己,我現在很高興從發現者身上發現了新消息,並且很高興在rxJava 2.0的菜單上看到Observable.Generate