我正在开发一个 Android 应用程序,供我工作的公司内部使用。我需要将文本文件保存在 Google 云端硬盘的共享云端硬盘上。 在我开发的 Web 应用程序中使用服务帐户之前,我已经这样做过几次,但我似乎无法在 Android 应用程序环境中正确设置连接。
我已经尝试过谷歌提供的示例https://developers.google.com/drive/api/v3/quickstart/java但似乎这与Android不兼容,因为它尝试使用库仅在桌面环境中可用。
这是我实现的代码:
// Implements OnClick for sendData button
public void onClickSendData(View view) {
try {
// Build a new authorized API client service.
final NetHttpTransport HTTP_TRANSPORT = new com.google.api.client.http.javanet.NetHttpTransport();
Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
// Upload file to google drive
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss", Locale.forLanguageTag("hu-HU")).format(new java.util.Date());
File fileMetadata = new File();
fileMetadata.setName("scan_" + timeStamp + ".txt");
fileMetadata.setParents(new ArrayList<String>(Arrays.asList(TARGET_FOLDER_ID)));
java.io.File filePath = new java.io.File(getFilesDir() + java.io.File.separator + BARCODE_CONTAINER_TEMP_FILE);
FileContent mediaContent = new FileContent("text/plain", filePath);
File file = service.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
barcodeContainer.setText(R.string.tarhely_ures);
barcodContainerEmptyFlag = true;
}
catch(Exception ex) {
// Handle any exception
ex.printStackTrace();
}
}
private Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
// Load client secrets.
InputStream in = MainActivity.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (in == null)
throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
java.io.File tokenFile = new java.io.File(getFilesDir() + java.io.File.separator + TOKENS_DIRECTORY_PATH);
if(!tokenFile.isDirectory())
tokenFile.mkdirs();
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(tokenFile))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
}
运行时错误如下:
java.lang.ClassNotFoundException: Didn't find class “java.awt.Desktop” in Android
我终于找到了问题的答案,这是我使用
GoogleCredential.Builder()
记录的解决方案这里:
// Upload file to google drive
public void uploadBarcodeFileToDrive() throws IOException, GeneralSecurityException {
// Get service account secret
InputStream inputStream = MainActivity.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (inputStream == null)
throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
// Convert inputStream to file
java.io.File clientSecret = new java.io.File(getFilesDir() + java.io.File.separator + "credentials.p12");
OutputStream outputStream = new FileOutputStream(clientSecret);
IOUtils.copy(inputStream, outputStream);
if (!clientSecret.exists())
throw new FileNotFoundException("Credentials (credentials.p12) not created from: " + CREDENTIALS_FILE_PATH);
// Http transport creation
HttpTransport httpTransport = AndroidHttp.newCompatibleTransport();
// Instance of the JSON factory
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
// Instance of the scopes required
List<String> scopes = new ArrayList<>();
scopes.add(DriveScopes.DRIVE);
// Build Google credential
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_PROVIDER)
.setServiceAccountScopes(scopes)
.setServiceAccountPrivateKeyFromP12File(clientSecret)
.setServiceAccountUser(SERVICE_ACCOUNT_USER)
.build();
// Build Drive service
Drive service = new Drive.Builder(httpTransport, jsonFactory, credential)
.setApplicationName(APPLICATION_NAME)
.build();
// Parents
List<String> parents = new ArrayList<>();
parents.add(TARGET_FOLDER_ID);
// Setup file
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss", Locale.forLanguageTag("hu-HU")).format(new java.util.Date());
File fileMetadata = new File();
fileMetadata.setName("scan_" + timeStamp + ".txt");
fileMetadata.setParents(parents);
java.io.File filePath = new java.io.File(getFilesDir() + java.io.File.separator + BARCODE_CONTAINER_TEMP_FILE);
FileContent mediaContent = new FileContent("text/plain", filePath);
// Upload file to google drive
service.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
}
问题中描述的示例的主要区别,以及当前的解决方案如下:
GoogleCredential.Builder()
,我需要在 dev.console 中为现有服务帐户创建一个 .p12
类型密钥。java.io.File
而不是 InputStream
,因此我从项目资产中读取它,并在调用方法时将其复制到内部存储。SERVICE_ACCOUNT_USER
应是服务帐户的 [..]@[..].iam.gserviceaccount.com
样式电子邮件地址。setServiceAccountUser(SERVICE_ACCOUNT_USER)
是必需的。