2

アプリケーションがデバイススリープや他のプログラムの切り替えなどのバックグラウンド状態から戻った後、Google Playサービスがnullポイント受信でクラッシュする理由を調べようとしています。場合によっては、Google Playサービスでアプリケーションの開始時にクラッシュポップアップが表示されることがあります。ですから、問題はrxjavaでスレッドが発生する場所なので、サービスのパス上のどこかにあると思います。Google ApiClientがnullであってはならない[Awareness API]

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

GoogleApiClientは@Singletonとして注入されます。私はこれがなぜ何時間も進歩なしに起こっているのを追跡しようとしています。

アプリケーションが問題なく動作するように続けて、「Googleはサービスのポップアップを再生する」のに迷惑ですが、私が見るgetuserLocAndWeatherに1つのコール()の戻りはプレイサービスをGoogleに接続を失ったが、それはすぐに有効な結果を返します。次の呼び出し。

MainActivityとGoogleApiServiceの実際のオブジェクト参照はnullではなく、[email protected]8e13のような参照は常に同じで、呼び出し時に常に接続されます。

トレース:

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) 

マイServiceクラス:,クライアントのための試み{}内のプリントアウトは常にある:真にかかわらず、Googleはサービスのクラッシュを再生するかどう。

クライアント:[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(); 

} 

使用法:あなたのOnStart()メソッドで

@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) 。ビルド(); } –

+0

@Tonyこれは、インジェクタで既に発生しています。オブジェクト自体は実際には見えないものではなく、MainActivityとGoogleApiServiceで常に同じ参照を持っています – buddhabath

+0

いつプログラムがクラッシュするのでしょうか? –

答えて

1

のみgoogleApiClientのオブジェクトを接続し、残りのもの私はonCreate()メソッドを実装します。

1

最初に私が行っているのは、onStart()のonResume()の部分であり、ユーザーが必要なときにそれらが存在することを確認するためです。アプリケーションが表示される前に最後に呼び出されたメソッドです。 onStop()とonPause()と同じことです。しかし何とかそれはあまりにも単純な答えのように思えるでしょう。

+0

ええ、onResume()では、なぜそれがそのような振る舞いをしているかを知るために移動を開始する前に、onResume()で実行したのではなく、その呼び出しをボタンにバインドしようとします問題を解決します。 – buddhabath

+0

ボタンに非同期にコールをバインドすることは、常に良いアイデアです。それがyr solution、buddhabathになったら、もう一方のスレッドをviewDetachに落とすことを検討してください。 DIを使用すると良いです。大好きです。 –

1

あなたのコードがcom.google.android.gms:73への呼び出しを開始する場所はおそらくAwareness.SnapshotApi.getWeather(client)なので、catchステートメントにNPEを追加することは実際には価値があります。特に断続的です。今

&他者への注意:私は、彼らはいくつかのスキルとrxJavaを使用していることがわかりので、私は唯一のこのことを示唆。 2つのモナド宣言の簡潔さを彼らのGoogleApiClientで見てください!彼らがする必要があるのは、retryWhen(Func2<Integer, Throwable, Boolean>)であり、上記の関数パラメータの述語を真であると評価すると、throwable instanceof NPEと1、おそらく2となります。ジップの前に、さらなるNPEのログ記録と解放NPEを捕まえることは絶対にありません。 ...この予測可能なイベントに適切な下流reactionsを提供しながら、または、それらの企業の鼻を微調整する場合は、教育を受け声が良い時間のように聞こえる、彼らはタイプによってさらに例外を除外することができ...

hmmmmm Kermit Sipping Tea

私は約ました言い換えれば、モナドにコードがたくさんぶら下がっているわけではないからです。create()メソッドは、それが副作用の一部になる可能性があることを望みます。しかし@buddhabath、私はそれらのcreate() sが正確にあなたが記述されているサブスクリプションの副作用を生成することができます注意してください - 右のサブスクリプションのスレッド上で、実際には:

あなたがcatching whatever comes out of those trysとrxChooChooをそれを下に送る「でなければなりません」と。現存するonErrorは問題ではないはずです。評価ごとに呼び出されるのは1つだけです。 subscriber.onError()でキャッチのパラメータを指すだけで、Throwable-excepting these Exceptionsはトラック内に保持されます(おそらく上記のKermitで説明したトラックのように)。しかし、create()があなたのバグです。

tl; dr:create()でモナドを手動で定義することには十分な注意が必要です。それは本当の世界、非常に「不可欠」です。文字通り何かが起こる可能性があります。私自身、新しいFromEmitterを発見したばかりの喜びを感じていて、rxJava 2.0のメニューでObservable.Generateを見てうれしいです。

関連する問題