本文介绍了在Android客户端身份验证的云端点间歇性故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在生产中的应用程序正在接收显著一些力/关闭调用一个身份验证的云端点时。最能说明问题的消息是java.lang.IllegalArgumentException:如果服务未注册:com.google.android.gms.internal.es@4481e6a8。逻辑正常工作95%的时间。失败的堆栈跟踪如下:

I have an application in production that is receiving a significant number of force/closes when calling an authenticated Cloud Endpoint. The most telling message is " java.lang.IllegalArgumentException: Service not registered: com.google.android.gms.internal.es@4481e6a8". The logic works correctly 95% of the time. The stack trace of the failure is as follows:

java.lang.RuntimeException的:执行时出错  doInBackground()的android.os.AsyncTask $ 3.done(AsyncTask.java:200)在  java.util.concurrent.FutureTask中$ Sync.innerSetException(FutureTask.java:273)  在java.util.concurrent.FutureTask.setException(FutureTask.java:124)  在java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:307)  在java.util.concurrent.FutureTask.run(FutureTask.java:137)在  java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)  在  java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:561)  在java.lang.Thread.run(Thread.java:1096)所引起的:  java.lang.IllegalArgumentException:如果服务未注册:  com.google.android.gms.internal.es@4481e6a8在  android.app.ActivityThread $ PackageInfo.forgetServiceDispatcher(ActivityThread.java:1074)  在android.app.ContextImpl.unbindService(ContextImpl.java:886)在  android.content.ContextWrapper.unbindService(ContextWrapper.java:352)  在com.google.android.gms.auth.GoogleAuthUtil.java.lang.String  为gettoken(android.content.Context,java.lang.String中,java.lang.String中)(未知  源)以  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)在  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)在  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)在  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)在  com.google.android.gms.auth.GoogleAuthUtil.java.lang.String  为gettoken(android.content.Context,java.lang.String中,java.lang.String中)(未知  源)以  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)在  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)在  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)在  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)在  com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.java.lang.String  为gettoken()(的SourceFile:192)在  com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.void  拦截(com.google.api.client.http.Htt prequest)(的SourceFile:217)在  com.google.api.client.http.Htt prequest.com.google.api.client.http.Htt presponse  执行()(的SourceFile:836)在  com.google.api.client.googleapis.services.AbstractGoogleClientRequest.com.google.api.client.http.Htt$p$psponse  executeUnparsed(布尔值)(的SourceFile:412)在  com.google.api.client.googleapis.services.AbstractGoogleClientRequest.com.google.api.client.http.Htt$p$psponse  executeUnparsed()(的SourceFile:345)在  com.google.api.client.googleapis.services.AbstractGoogleClientRequest.java.lang.Object  执行()(的SourceFile:463)在  com.jdub.empiretracker.EmpireTrackerActivity$QueryMarketStats.com.google.api.services.marketendpoint.model.Market  doInBackground(com.google.api.services.marketendpoint.model.Market [])(的SourceFile:355)  在  com.jdub.empiretracker.EmpireTrackerActivity $ QueryMarketStats.java.lang.Object  doInBackground(java.lang.Object中[])(的SourceFile:1)在  android.os.AsyncTask $ 2.call(AsyncTask.java:185)在  java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305)...  4个

我的实现与谷歌的样本非常一致。例如,我的机器人活动是使用的AsyncTask拨打电话,具体如下:

My implementation is very consistent with the Google samples. For example, my Android activity is using an AsyncTask to make the call, as follows:

    private class QueryMarketStats extends AsyncTask<com.google.api.services.marketendpoint.model.Market, com.google.api.services.marketendpoint.model.Market, com.google.api.services.marketendpoint.model.Market> {

    /* (non-Javadoc)
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected com.google.api.services.marketendpoint.model.Market doInBackground(com.google.api.services.marketendpoint.model.Market...markets) {

        com.google.api.services.marketendpoint.model.Market result = null;

        try {
            result = service.market().latest(state.getServerID()).execute();
        }
        catch (SSLException e) {
            PrimeDataStore();
            Log.d("app", e.getMessage(), e);
        }
        catch (GoogleAuthIOException e) {
            Log.d("app", e.getMessage(), e);
        }
        catch (IOException e) {
            Log.d("app", e.getMessage(), e);
        }

        return result;
    }

    /* (non-Javadoc)
     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
     */
    @Override
    protected void onPostExecute(com.google.api.services.marketendpoint.model.Market result) {

        // Process result...
    }

}

该行给出错误的是:。的结果= service.market()最新(state.getServerID())执行();

The line giving the error is:result = service.market().latest(state.getServerID()).execute();

我已经验证了getServerID参数()返回一个值,该值是可以接受的。我在这一点上的理论是,谷歌播放服务是不是能够提供通过身份认证的帐户。虽然我已经无法重现,我相信当应用程序进入睡眠状态可能会出现问题。因此,我证实了我的onResume()的逻辑,如下:

I have verified the parameter for getServerID() is returning a value that is acceptable. My theory at this point is that Google Play Services is not able to provide an account that is still authenticated. Although I have been unable to reproduce, I believe the issue may occur when the application goes to sleep. I therefore confirmed my onResume() logic, as follows:

    @Override
protected void onResume() {
    super.onResume();
    checkPlayServices();
    isInFront = true;
}

还有什么可能导致此间歇性故障?这是一个已知的问题?

What else could cause this intermittent failure? Is this a known issue?

推荐答案

在代替一个更好的选择,我捕捉异常,并触发成功重试。无论间歇性问题,导致该端点被称为不能在时间点登记的服务,服务的工作将来调用正常。

In lieu of a better alternative, I am catching the exception and triggering a retry with success. Whatever intermittent issue is causing the service not to be registered at the point in time the endpoint is called, future invocations of the service work properly.

工作,围绕code

@Override
protected com.google.api.services.marketendpoint.model.Market doInBackground(com.google.api.services.marketendpoint.model.Market...markets) {

    com.google.api.services.marketendpoint.model.Market result = null;

    try {
        result = service.market().latest(state.getServerID()).execute();
    }
    catch (SSLException e) {
        PrimeDataStore();
        Log(e);
    }
    catch (GoogleAuthIOException e) {
        Log(e);
    }
    catch (IOException e) {
        Log(e);
    }
    catch (IllegalArgumentException e) {
        // This caused a lot of intermittent force/closes.
        Log(e);
    }

    return result;
}

@Override
protected void onPostExecute(com.google.api.services.marketendpoint.model.Market result) {

    DismissProgressDialogIfPresent();

    com.google.api.services.marketendpoint.model.Market m = (com.google.api.services.marketendpoint.model.Market) result;

    if( m == null)
    {
        // Verify the current activity is active
        if( isInFront ) {

            // Present a retry/cancel dialog
            AlertDialog.Builder builder = new AlertDialog.Builder(EmpireTrackerActivity.this);
            builder.setMessage("An error was encountered retrieving the latest market data.\n\nPlease verify you are connected to the Internet.");
            builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();

                    m_ProgressDlg = ProgressDialog.show(EmpireTrackerActivity.this, "Please wait...", "Retrieving data ...", true);
                    new QueryMarketStats().execute();
                }
            });
            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {

                    dialog.dismiss();
                }
            });
            AlertDialog alert = builder.create();
            alert.show();
        }

        return;
    }

    // Process newly posted data
    state.setMarketObj(m);
    state.setIsInitialized(true);
    state.WriteFile(EmpireTrackerActivity.this);

    super.onPostExecute(result);
}

}

这篇关于在Android客户端身份验证的云端点间歇性故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 03:39