GoogleAccountCredential - [ERROR]名称不能为空:null - 尽管权限

时间:2016-12-19 09:35:01

标签: android google-sheets runtime-error google-account

我一直在开发一款应用程序,可以在某些时刻将一小部分数据发送回Google Sheet,但是我无法让它正常工作:

public void SheetUpdate() {
    GoogleAccountCredential mCredential;

    Sheets mService;
    final String[] SCOPES = { SheetsScopes.SPREADSHEETS };

    mCredential = GoogleAccountCredential.usingOAuth2(getApplicationContext(), Arrays.asList(SCOPES))
            .setBackOff(new ExponentialBackOff())
            .setSelectedAccountName("oscarcookeabbott@gmail.com");

    Log.e("DEBUG", "SheetUpdate: " + mCredential.getSelectedAccountName());

    HttpTransport transport = AndroidHttp.newCompatibleTransport();
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();

    mService = new Sheets.Builder(transport, jsonFactory, mCredential)
            .setApplicationName("Listeau")
            .build();

    /*
    String range = "[Sheet Name]![Start]:[End]";

    mService.spreadsheets().values().update(enumId, range, valueRange)
            .setValueInputOption("RAW")
            .execute();
    */

    ValueRange values = new ValueRange();
    values.set("EMAIL", "tonyjones@abc.net.au");
    values.set("AUTH", "[INSERT DATE]");
    values.set("SUB", "[INSERT DATE + MONTH]");

    try {
        mService.spreadsheets().values().append("1meAAvjdPmghn6wl_IKc-_NJx_M85I_yqsn4Nwm_j_X0", "Users", values)
                .setValueInputOption("RAW")
                .execute();
    } catch(IOException e) {
        Log.e("BUG", "SheetUpdate: IOException");
    }
}

在我的清单中,我有:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>

我收到的错误指向mCredential,因为它的名称未设置(null),在调用mService.execute时会被捕获。 我手动(只是为了尝试并查明问题)允许在Settings-Apps菜单中使用权限,以及在Jellybean上尝试过,但所有人都声称存在同样的问题。

[编辑]这是完整的错误输出: `

E/AndroidRuntime: FATAL EXCEPTION: main
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pybuspr.listeriafoodusa/com.pybuspr.listeau.Master}: java.lang.IllegalArgumentException: the name must not be empty: null
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
                      at android.app.ActivityThread.access$600(ActivityThread.java:130)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
                      at android.os.Handler.dispatchMessage(Handler.java:99)
                      at android.os.Looper.loop(Looper.java:137)
                      at android.app.ActivityThread.main(ActivityThread.java:4745)
                      at java.lang.reflect.Method.invokeNative(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:511)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
                      at dalvik.system.NativeStart.main(Native Method)
                   Caused by: java.lang.IllegalArgumentException: the name must not be empty: null
                      at android.accounts.Account.<init>(Account.java:48)
                      at com.google.android.gms.auth.zze.getToken(Unknown Source)
                      at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
                      at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:269)
                      at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:294)
                      at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:868)
                      at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
                      at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
                      at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
                      at com.pybuspr.listeau.Master.SheetUpdate(Master.java:167)
                      at com.pybuspr.listeau.Master.onCreate(Master.java:48)
                      at android.app.Activity.performCreate(Activity.java:5008)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 
                      at android.app.ActivityThread.access$600(ActivityThread.java:130) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 
                      at android.os.Handler.dispatchMessage(Handler.java:99) 
                      at android.os.Looper.loop(Looper.java:137) 
                      at android.app.ActivityThread.main(ActivityThread.java:4745) 
                      at java.lang.reflect.Method.invokeNative(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:511) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
                      at dalvik.system.NativeStart.main(Native Method)

`

2 个答案:

答案 0 :(得分:0)

您的execute()来自您创建的GoogleAccountCredential对象,并且内部失败。

查看开源的Account.java代码,可以看到传入的名称为null。呼叫者GoogleAuthUtil是Play服务库的一个封闭源代码部分,但我们可以很好地猜测正在发生的事情。它会尝试从手机设置中获取Google帐户,但无法找到匹配项。

正如您已经怀疑的那样,权限是一个因素,我认为这是您失败的原因。在定位Android 6及更高版本时,在清单中声明权限可能不够,在您的情况下,GET_ACCOUNTS会受此影响。请参阅here

您需要在运行时请求权限(并清楚地处理用户拒绝它们的情况)。有关如何执行此操作,请参阅here。或者,如果您没有任何相关的依赖关系,则可以将目标级别降低到5.1或更低,现在至少,它将使用较旧的权限模型。

答案 1 :(得分:0)

今天我遇到了同样的错误。但是终于我成功了。我在这里描述了我所做的事情,以便对任何人都有帮助。

所以,原因是:mCredential.getSelectedAccountName() == null

所以,我这样称呼api调用是否成功:

 private void getResultsFromApi() {
        if (! isGooglePlayServicesAvailable()) {
            acquireGooglePlayServices();
        } else if (mCredential.getSelectedAccountName() == null) {
            chooseAccount();
        } else if (! isDeviceOnline()) {
            mOutputText.setText("No network connection available.");
        } else {

            Toast.makeText(this, "API CALL SUCCESS", Toast.LENGTH_SHORT).show();

          }
    }

当我收到上述消息API CALL SUCCESS时,我将调用readData或Append Data函数。然后读取或追加数据。

因此,请仔细检查您的代码,初始化,实现,权限等,以确保mCredential.getSelectedAccountName() != null成功。