该应用已在“Google API控制台”中注册为“已安装的应用” - 似乎这是Android应用的正确设置,不是吗?
所以我确实有一个Client-Id而且没有Secret-Id。要说清楚:它不是Web应用程序,也不是Google Drive-App--它是一个Android应用程序,用于访问Google云端硬盘云中的其他用户数据。
在应用程序中,我获取帐户(工作),我确实请求令牌(工作)。现在,我想使用该令牌和Client-Id连接到Google云端硬盘。结果是“401,无效凭证”。这段代码出了什么问题?
public class ActivityMain extends Activity implements DialogInterface.OnClickListener {
// https://developers.google.com/drive/scopes
private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/drive";
// https://code.google.com/apis/console/
private static final String CLIENT_ID = "999999999999999.apps.googleusercontent.com";
private AccountManager accountManager;
private Account[] accounts;
private String authName;
private String authToken;
@Override
public void onClick(final DialogInterface dialogInterface, final int item) {
processAccountSelected(accounts[item]);
}
@Override
public void onCreate(final Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activitymain);
accountManager = AccountManager.get(this);
accounts = accountManager.getAccountsByType("com.google");
if (accounts == null || accounts.length == 0) {
// TODO
} else if (accounts.length == 1) {
processAccountSelected(accounts[0]);
} else if (accounts.length > 1) {
showDialog(MyConstants.DIALOG_ACCOUNTCHOSER);
}
}
@Override
protected Dialog onCreateDialog(final int id) {
switch (id) {
case MyConstants.DIALOG_ACCOUNTCHOSER:
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
String[] names = new String[accounts.length];
for (int i = 0; i < accounts.length; i++) {
names[i] = accounts[i].name;
}
alertDialogBuilder.setItems(names, this);
alertDialogBuilder.setTitle("Select a Google account");
return alertDialogBuilder.create();
}
return null;
}
private void processAccountSelected(final Account account) {
if (account != null) {
authName = account.name.toString();
if (!Tools.isEmpty(authName)) {
Toast.makeText(this, authName, Toast.LENGTH_LONG).show();
accountManager.getAuthToken(account, AUTH_TOKEN_TYPE, null, this,
new AccountManagerCallback<Bundle>() {
public void run(final AccountManagerFuture<Bundle> future) {
try {
authToken = future.getResult().getString(
AccountManager.KEY_AUTHTOKEN);
processTokenReceived();
} catch (OperationCanceledException exception) {
// TODO
} catch (Exception exception) {
Log.d(this.getClass().getName(), exception.getMessage());
}
}
}, null);
}
}
}
private void processListFiles(final Drive drive) {
List<File> result = new ArrayList<File>();
Files.List request = null;
try {
request = drive.files().list();
} catch (IOException exception) {
}
do {
try {
FileList files = request.execute();
result.addAll(files.getItems());
request.setPageToken(files.getNextPageToken());
} catch (IOException exception) {
// --> 401 invalid credentials
}
} while (request.getPageToken() != null && request.getPageToken().length() > 0);
}
private void processTokenReceived() {
if (!Tools.isEmpty(authToken)) {
final HttpTransport transport = AndroidHttp.newCompatibleTransport();
final JsonFactory jsonFactory = new GsonFactory();
GoogleCredential credential = new GoogleCredential();
credential.setAccessToken(authToken);
Drive drive = new Drive.Builder(transport, jsonFactory, credential)
.setApplicationName(getString(R.string.txt_appname))
.setJsonHttpRequestInitializer(new GoogleKeyInitializer(CLIENT_ID))
.build();
if (drive != null) {
processListFiles(drive);
}
}
}
}
我不得不说这是一堆乱七八糟的东西。网页上有很多页面只显示部分,有很多页面使用弃用,缺失或不同的方法来做同样的事情。在我看来,有两个页面显示了从Android应用中从Google云端硬盘获取数据的相同方式。
非常感谢任何帮助。
编辑:我可以自己解决。这是不同变化的组合:
这是获取云端硬盘对象的当前部分:
GoogleCredential credential = new GoogleCredential();
credential.setAccessToken(authToken);
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = new AndroidJsonFactory();
drive = new Drive.Builder(transport, jsonFactory, credential)
.setApplicationName(getString(R.string.txt_appname))
.setJsonHttpRequestInitializer(
new GoogleKeyInitializer(APIKEY_SIMPLE))
.build();
if (drive != null) {
}
答案 0 :(得分:3)
是的,文档很难流行。
只需更改
new GoogleKeyInitializer(CLIENT_ID)
到
new GoogleKeyInitializer(SIMPLE_API_ACCESS_KEY)
它应该有用。
您可以在 API访问页面的{strong>简单API访问部分({{1})下的Google APIs Console中找到您的SIMPLE_API_ACCESS_KEY
})。如果此部分不可用,您必须先在服务页面上激活Drive API访问权限。
答案 1 :(得分:1)
您收录的代码段有2个问题。
在从AccountManager获取新的authToken
之前,必须使旧的authToken无效。
AccountManager.get(activity).invalidateAuthToken("com.google", authToken);
accountManager.getAuthToken(...);
对setJsonHttpRequestInitializer
的调用必须使用API控制台中为您的项目声明的简单API密钥。
在构建Drive对象时设置API密钥。
.setJsonHttpRequestInitializer(new GoogleKeyInitializer(KEY))
此处有一个小样本证明令牌失效:http://chiarg.com/?p=429
答案 2 :(得分:0)
我尝试了所有这些,最后发现此代码可以与google日历API一起使用。每次我使用GoogleCredentials并将其传递给构建版本时,我都会获得401。
HttpTransport transport = AndroidHttp.newCompatibleTransport();;
JsonFactory jsonFactory = new GsonFactory();
HttpRequestInitializer httpRequestInitializer;
Log.i("Reached calendar builder", "Reached calendar builder"+accessToken);
//GoogleCredential credential = new GoogleCredential();
httpRequestInitializer = new HttpRequestInitializer(){
public void initialize(HttpRequest request) throws IOException
{
request.getHeaders().setAuthorization(GoogleHeaders.getGoogleLoginValue(accessToken));
}
};
Calendar service = new Calendar.Builder(transport, jsonFactory, httpRequestInitializer)
.setApplicationName("Meetrbus/1.0")
.setJsonHttpRequestInitializer(new GoogleKeyInitializer("API_KEY"))
.build();
}
答案 3 :(得分:0)
我在此处广泛回答了在Android上使用Google云端硬盘的问题:
Android Open and Save files to/from Google Drive SDK
使用我在答案中列出的方法,我可以确认您能够执行以下操作: