GoogleApiClient不得为空[Awareness API] [英] GoogleApiClient must not be null [Awareness API]

查看:97
本文介绍了GoogleApiClient不得为空[Awareness API]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找出为什么应用从后台状态(例如设备休眠或切换其他程序)返回后,Google Play服务为何会崩溃并导致nullpointerexception异常。有时,Google Play服务会在应用程序启动时弹出崩溃弹出窗口。因此,我认为问题出在服务路径上的某个地方,因为使用rxjava进行线程化。

 注意:在MainActivity(字段注入)和GoogleApiService(构造函数注入)中都注入GoogleApiClient。 

GoogleApiClient作为@Singleton注入。我一直在尝试跟踪为什么现在要花几个小时才能进行,但是没有任何帮助。



该应用程序可以继续正常运行,没有任何问题, Google Play服务弹出窗口虽然很烦人,但我看到一个对getuserLocAndWeather()的调用返回了与Google Play服务的连接丢失,但在下一个调用中它立即返回了有效结果。 b $ b

MainActivity和GoogleApiService中的实际对象引用永远不会为null,引用始终是相同的,例如com.google.android.gms.internal.zzqd@a768e13,并且在调用时始终保持连接。



迹线:

 致命例外:lowpool [3] 
流程:com.google.android.gms.persistent,PID:12828
java.lang.NullPointerException:ilk.a(:com.google.android.gms:73)的GoogleApiClient不得为空

在hys。< init>(:com.google.android.gms:115)
在pof。< init>(:com.google.android.gms:86)
在ppz处。< init>(:com.google.android.gms:35)在ppx处
。< init>(:com.google.android.gms:179)在ppp.a处
(:com.google.android.gms:179)buc.a(:com.google.android.gms:381)
jfo.run(:com.google.android.gms: 1087)在itt.run处
(:com.google.android.gms:453)在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)处
在java。 util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:587)
在iyg.run(:com.google.android.gms:17)
在java.lang.Thread.run(Thread .java:818)

我的服务类:在客户端的try {}中打印出来始终为true,无论Google Play服务是否崩溃。



客户端:com.google.android.gms.internal.zzqd@3c738f4e是否已连接? :true

 公共类GoogleApiService实现IGoogleApi {
私有GoogleApiClient客户端;
private static final String TAG = GoogleApiClient;

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

}


public Observable< UserCurrentInfo> getLocationWeather(){
Observable< WeatherResult> weatherObservable = Observable.create(订阅者-> {

try {
Log.d(TAG,试图获取天气));
Log.d(TAG, Client: + client.toString()+ Connected?: + client.isConnected());


Awareness.SnapshotApi.getWeather(client)
.setResultCallback (天气-> {
if(!weather.getStatus()。isSuccess()){
Subscriber.onError(new Throwable(无法获得天气)));
日志。 d(TAG,获取天气时出错 + weather.getStatus()。toString());

} else {
Log.d(TAG,获取天气情况);
Subscriber.onNext(天气);
Subscriber.onCompleted();
}
});
} catch(SecurityException e){
抛出新的Se curityException(没有权限: + e);

}
});



Observable< LocationResult> locationObservable = Observable.create(订阅者-> {
try {
Awareness.SnapshotApi.getLocation(client)
.setResultCallback(retrievedLocation-> {
if(!retrievedLocation。 getStatus()。isSuccess()){
subscription.onError(new Throwable(无法获取位置。));
Log.d(TAG,获取位置错误);

} else {
users.onNext(retrievedLocation);
Subscriber.onCompleted();
}
});
} catch(SecurityException e ){
抛出新的SecurityException(无权限: + e);

}
});

返回Observable.zip(weatherObservable,locationObservable,
(天气,位置)-> {
返回新的UserCurrentInfo(weather.getWeather(),location.getLocation()) ;
});
}

演示者:

 公共类FavouritesPresenter实现BasePresenter< IFavouriteView> {

私有IFavouriteView favView;
private String TAG = FavPresenter;
私人订阅订阅;
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,,);}
);
}

用例:

 公共类GetUserLocationWeatherUseCase实现Usecase< UserCurrentInfo> {
IGoogleApi apihelper;

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

}

主要活动的用法:

  @注入
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客户端){
this.connectionCallbacks = new GoogleApiClient.ConnectionCallbacks(){
@Override
public void onConnected(@Nullable Bundle bundle)
的收藏夹Presenter.getUserLocAndWeather(); //呼叫发起者以启动可观察的链,实际上这是在进行GPS检查等之后才出现的,但是为了更容易凝聚,
}
@Override
public void onConnectionSuspended(int i){}
};
client.registerConnectionCallbacks(this.connectionCallbacks);
}


解决方案

我认为 Awareness.SnapshotApi.getWeather(client)可能是您的代码开始调用 com.google.android.gms:73 的地方,因此,在您的catch语句中添加NPE实际上可能是值得的,尤其是因为它是间歇性的。



&现在给其他人的注释:我建议这样做,因为我发现他们使用rxJava具有一定的技巧;看看它们的 GoogleApiClient 中两个monad声明的简洁性!他们所需要做的就是 retryWhen(Func2< Integer,Throwable,Boolean>)并在给定 throwable的情况下将所述功能参数中的谓词评估为真NPE实例,计数为1,可能为2。在压缩之前,我认为记录并发布更多NPE(使进一步的异常行为显而易见)可能会满足那些坚定而受过教育的声音,告诉我们永远不要赶上NPE。 ...或者,如果调整那些坚定,受过良好教育的声音听起来像是个好时机,那么他们可以按类型过滤出更多的异常,同时提供适当的下游



我要说的是,您可以这样做,因为monad中没有很多代码希望它可以是副作用的一部分的create()方法;但是@buddhabath,我注意到那些 create()可以完全生成您正在描述的订阅副作用-实际上在订阅线程上:



您应该 从所有尝试 s 中捕获任何并将其发送到rxChooChoo; onError 应该不是问题b / c每次评估仅会调用一个。
只需将catch的参数指向Subscriber.onError()和任何Throwable- 除了这些异常-将保留在轨道内,也许就像我在柯密特上面描述的轨道一样,但泄漏的 create()是您的错误。



tl; dr:使用 create()应该引起我们的全力注意;这是现实世界,非常势在必行;实际上,那里什么都可能发生。我自己,很高兴能从Emitter中发现新的东西,也很高兴看到 Observable.Generate 在rxJava 2.0的菜单上。


I'm trying to find out why the Google Play Services is crashing with a nullpointerexception after the application is coming back from a background state such as device sleep or toggle other program. Sometimes Google Play Services gives the crash popup on application start. So I assume the problem lies somewhere on the path to the service since there is where the threading occurs with rxjava.

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

GoogleApiClient is injected as a @Singleton. I've been trying to trace why this is happening for hours now without progress, any help appreciated.

The Application continues to work without any issues, the "Google Play Services popup" is annoying though, I see one call to getuserLocAndWeather() return lost connection to google play services, but it immediatly returns a valid result in the next call.

The actual object reference in MainActivity and GoogleApiService is never null, the reference is always the same, like com.google.android.gms.internal.zzqd@a768e13 and always connected when the call is made.

Trace:

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)

My Service class:, the print out in the try{} for the client is always : true, regardless if google play services crashes or not.

Client: com.google.android.gms.internal.zzqd@3c738f4e Connected? :true

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());
            });
}

Presenter:

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

Usecase:

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

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

}

Usage in mainactivity:

@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);
}

解决方案

I assume that Awareness.SnapshotApi.getWeather(client) is probably where your code begins the call to com.google.android.gms:73, so adding the NPE to your catch statement actually might be worth, particularly as it's intermittent.

& now a Note to others: I only suggest this because I see that they're using rxJava with some skill; look at the terseness of the two monad declarations in their GoogleApiClient! All they need to do is a retryWhen(Func2<Integer, Throwable, Boolean>) and evaluate the predicate in said functional parameter to be true given throwable instanceof NPE and count of 1, maybe 2. Before the zip, I think logging and releasing further NPEs--making further anomalous behavior apparent--might satisfy the firm, educated voices telling us never, ever to catch an NPE. ...or, if tweaking the noses of those firm, educated voices sounds like a good time, they could filter out further Exceptions by type while providing appropriate downstream reactions to this predictable event...

I was about to say that you can do that because there isn't a bunch of code hanging around in the monad create() methods wishing it could be part of a side effect; however @buddhabath, I notice those create()s can generate exactly the subscription side effect you are describing--right on the subscription thread, actually:

You "should be" catching whatever comes out of those trys and sending it down the rxChooChoo; the extant onError shouldn't be a problem b/c only one will be called per evaluation. Just point the parameter of the catch at subscriber.onError() and any Throwable-excepting these Exceptions-will be kept within the tracks, perhaps like the tracks I described above the Kermit, but that leaking create() is your bug.

tl;dr: Manually defining monads with create() deserves one's full attention; it's the real world, very "imperative"; literally anything could happen in there. Myself, I just now had the pleasure of discovering the new fromEmitter and also am glad to see Observable.Generate on the menu for rxJava 2.0.

这篇关于GoogleApiClient不得为空[Awareness API]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆