private void common_query_file( final String data, final Mode mode, final GenericCallback<String> resultCallback) { Query query = new Query.Builder() .addFilter(Filters.eq(SearchableField.TITLE, DH_DRIVE_FILENAME)) .addFilter(Filters.eq(SearchableField.MIME_TYPE, "text/plain")) .build(); Drive.DriveApi.query(client, query) .setResultCallback( new ResultCallback<DriveApi.MetadataBufferResult>() { @Override public void onResult(MetadataBufferResult result) { MetadataBuffer buffer = result.getMetadataBuffer(); if (buffer.getCount() > 0) { ArrayList<Metadata> list = new ArrayList<Metadata>(); Iterator<Metadata> iterator = buffer.iterator(); while (iterator.hasNext()) { Metadata metadata = iterator.next(); if (!metadata.isTrashed()) { list.add(metadata); } } if (!list.isEmpty()) { DriveId id = list.get(0).getDriveId(); DriveFile file = Drive.DriveApi.getFile(client, id); System.out.println("# " + file.toString()); // Read file no matter what common_read(file, data, mode, resultCallback); } else { switch (mode) { case DOWNLOAD: resultCallback.onResult(GenericCallback.NO_FILE); break; case UPLOAD: upload_create_contents(/*folder,*/ data, resultCallback); break; } } } else { switch (mode) { case DOWNLOAD: resultCallback.onResult(GenericCallback.NO_FILE); break; case UPLOAD: upload_create_contents(/*folder,*/ data, resultCallback); break; } } buffer.close(); } }); }
/** * Helper just to avoid copy&paste'ing code. * * <p>Note: since this contains blocking Drive API calls, this will crash if you try to call it * from the main thread, it can only be called from other threads. * * @return null if the folder can not be found. */ private DriveFolder checkOrCreateRemoteFolder( GoogleApiClient googleApiClient, DriveFolder rootFolder, String folderName) { // check for STORAGE permission if (!canWriteToStorage()) return null; Query query = new Query.Builder() .addFilter( Filters.and( Filters.eq(SearchableField.TITLE, folderName), Filters.contains(SearchableField.MIME_TYPE, "folder"))) .build(); DriveApi.MetadataBufferResult result = rootFolder.queryChildren(mGoogleApiClient, query).await(); if (!result.getStatus().isSuccess()) { Log.e( mActivity.getResources().getString(R.string.app_name), "Cannot query folders in the root of Google Drive."); return null; } else { for (Metadata m : result.getMetadataBuffer()) { if (m.getTitle().equals(folderName)) { // Folder exists - we found it! DriveFolder folder = m.getDriveId().asDriveFolder(); result.getMetadataBuffer().release(); return folder; } } } result.getMetadataBuffer().release(); // Folder not found; let's create it. MetadataChangeSet changeSet = new MetadataChangeSet.Builder().setTitle(folderName).build(); DriveFolder.DriveFolderResult result1 = rootFolder.createFolder(googleApiClient, changeSet).await(); if (!result1.getStatus().isSuccess()) { Log.e( mActivity.getResources().getString(R.string.app_name), "Error while trying to create the folder \"" + folderName + "\""); return null; } return result1.getDriveFolder(); }
public void loadForm( final GoogleApiClient googleClient, final Activity activity, final String formName) { if (loadFormFromLocalStorage(activity, formName)) { return; } Query.Builder queryBuilder = new Query.Builder(); Log.i( MainActivity.PT_APP_INFO, "Load form from cloud. Google client state " + googleClient.isConnected()); queryBuilder.addFilter(Filters.eq(SearchableField.TITLE, formName)); Query query = queryBuilder.build(); final DriveFolder driveFolder = Drive.DriveApi.getFolder(googleClient, storageDriveId); Toast.makeText(activity, "Loading " + formName + " from google drive... ", Toast.LENGTH_LONG) .show(); driveFolder .queryChildren(googleClient, query) .setResultCallback( new ResultCallback<DriveApi.MetadataBufferResult>() { @Override public void onResult(DriveApi.MetadataBufferResult resultBufferResult) { if (resultBufferResult.getMetadataBuffer().getCount() > 0) { DriveFile driveFile = Drive.DriveApi.getFile( googleClient, resultBufferResult.getMetadataBuffer().get(0).getDriveId()); driveFile .open(googleClient, DriveFile.MODE_READ_ONLY, null) .setResultCallback( new ResultCallback<DriveApi.DriveContentsResult>() { @Override public void onResult(DriveApi.DriveContentsResult driveContentsResult) { try { InputStream is = driveContentsResult.getDriveContents().getInputStream(); FormTemplateManager.loadForm(is); LocalDriver.save( FormTemplateManager.getFormTemplate(), GoogleFileType.FORM, formName); goBackToMain(activity); } catch (Throwable th) { String errorStr = "Unable to retrieve form " + formName + " because " + th + " Retrieving from local drive"; Toast.makeText(activity, errorStr, Toast.LENGTH_LONG).show(); Log.e(MainActivity.PT_APP_INFO, errorStr); } } }); } } }); }
public void saveOrUpdate( final FormTemplate formToSave, final GoogleApiClient googleClient, final GoogleFileType googleFileType) throws GoogleDriverException { LocalDriver.save(formToSave, googleFileType, null); if (storageDriveId == null) { throw new GoogleDriverException("Cannot found form directory on google drive"); } final DriveId dirDriveId; if (googleFileType == GoogleFileType.REPORT) { dirDriveId = reportDriveId; } else { dirDriveId = storageDriveId; } final String fileName = PhysicalTherapyUtils.getFileName(formToSave); Query.Builder queryBuilder = new Query.Builder(); queryBuilder.addFilter(Filters.eq(SearchableField.TITLE, fileName)); Query query = queryBuilder.build(); try { final DriveFolder driveFolder = Drive.DriveApi.getFolder(googleClient, dirDriveId); driveFolder .queryChildren(googleClient, query) .setResultCallback( new ResultCallback<DriveApi.MetadataBufferResult>() { @Override public void onResult(DriveApi.MetadataBufferResult resultBufferResult) { DriveId fileDriveId = null; for (Metadata result : resultBufferResult.getMetadataBuffer()) { fileDriveId = result.getDriveId(); } if (fileDriveId == null) { save(formToSave, googleClient, dirDriveId, fileName); } else { update(formToSave, googleClient, fileDriveId, fileName); } } }); } catch (Throwable th) { throw new GoogleDriverException("Unable to find or save file to drive because " + th, th); } }
private void setStorageDirectory(final GoogleApiClient googleClient) throws GoogleDriverException { Query.Builder queryBuilder = new Query.Builder(); queryBuilder.addFilter(Filters.eq(SearchableField.TITLE, STORAGE_DIR)); Query query = queryBuilder.build(); try { final DriveFolder driveFolder = Drive.DriveApi.getRootFolder(googleClient); driveFolder .queryChildren(googleClient, query) .setResultCallback( new ResultCallback<DriveApi.MetadataBufferResult>() { @Override public void onResult(DriveApi.MetadataBufferResult resultBufferResult) { for (Metadata result : resultBufferResult.getMetadataBuffer()) { if (result.getTitle().equals(STORAGE_DIR)) { storageDriveId = result.getDriveId(); getAllForms(googleClient); } } if (storageDriveId == null) { MetadataChangeSet.Builder builder = new MetadataChangeSet.Builder(); builder.setTitle(STORAGE_DIR); driveFolder .createFolder(googleClient, builder.build()) .setResultCallback( new ResultCallback<DriveFolder.DriveFolderResult>() { @Override public void onResult( DriveFolder.DriveFolderResult driveFolderResult) { storageDriveId = driveFolderResult.getDriveFolder().getDriveId(); } }); } } }); } catch (Throwable th) { throw new GoogleDriverException( "Unable to find or create google drive storage directory because " + th, th); } }
private void syncPhotosForTeam(GoogleApiClient googleApiClient, int teamNumber) { if (mTeamNumber >= 0) { Log.i( mActivity.getResources().getString(R.string.app_name), "Beginning photo sync for team " + teamNumber); // get the list of local files File photosDir = new File(mLocalTeamPhotosFilePath + "/" + teamNumber); /** **** get the list of local files ***** */ // check if that folder exists if (!photosDir.isDirectory()) { // we have no photos for this team if (mRequester != null) mRequester.updatePhotos(new Bitmap[0]); googleApiClient.disconnect(); return; } File[] listOfFiles = photosDir.listFiles(); ArrayList<String> arrLocalFiles = new ArrayList<String>(); for (File file : listOfFiles) { // make sure it's an image file Bitmap bitmap = BitmapFactory.decodeFile(file.getPath()); if (bitmap != null) { arrLocalFiles.add(file.getPath()); } // else: if it's not a file, then what is it???? .... skip I guess } // Navigate to the correct folder - there has to be a more efficient way to do this DriveFolder rootFolder = Drive.DriveApi.getFolder(googleApiClient, mDriveIdTeamPhotosFolder); Log.i( mActivity.getResources().getString(R.string.app_name), "Local Files: " + arrLocalFiles); Query query = new Query.Builder() .addFilter(Filters.eq(SearchableField.TITLE, "" + teamNumber)) .build(); DriveApi.MetadataBufferResult result = rootFolder.queryChildren(googleApiClient, query).await(); DriveFolder teamPhotosFolder = null; for (Metadata m : result.getMetadataBuffer()) { teamPhotosFolder = m.getDriveId().asDriveFolder(); } result.getMetadataBuffer().close(); ArrayList<PathAndDriveId> arrRemoteFiles = new ArrayList<PathAndDriveId>(); if (teamPhotosFolder != null) { query = new Query.Builder() .addFilter( Filters.eq(SearchableField.MIME_TYPE, "application/vnd.google-apps.photo")) .build(); result = teamPhotosFolder.queryChildren(googleApiClient, query).await(); for (Metadata m : result.getMetadataBuffer()) { arrRemoteFiles.add( new PathAndDriveId( mRemoteToplevelFolderName + "/" + mRemoteTeamFolderName + "/" + mRemoteTeamPhotosFolderName + "/" + mTeamNumber + "/" + m.getTitle(), m.getDriveId(), m.getTitle())); } result.getMetadataBuffer().close(); } Log.i( mActivity.getResources().getString(R.string.app_name), "Remote Files: " + arrRemoteFiles); // Remove files that are in both lists - these don't need to be synced. for (PathAndDriveId remoteFile : arrRemoteFiles) { String remotePath = remoteFile.path; if (arrLocalFiles.contains(remotePath)) { arrRemoteFiles.remove(remoteFile); arrLocalFiles.remove(remotePath); } } /** **** Download any Files we're missing locally ***** */ for (PathAndDriveId remoteFile : arrRemoteFiles) { // the Drive API actually makes a local cache of the file, so let's copy the contents into // our app's file structure DriveApi.DriveContentsResult fileResult = remoteFile .driveId .asDriveFile() .open(googleApiClient, DriveFile.MODE_READ_ONLY, null) .await(); if (!fileResult.getStatus().isSuccess()) { // file can't be opened continue; } String localFileToCreate = mLocalTeamPhotosFilePath + "/" + teamNumber + "/" + remoteFile.title; DriveContents contents = null; InputStream in = null; FileOutputStream fout = null; try { // DriveContents object contains pointers to the actual byte stream, which we will // manually copy contents = fileResult.getDriveContents(); in = contents.getInputStream(); fout = new FileOutputStream(localFileToCreate); // read bytes from source file and write to destination file byte[] b = new byte[1024]; int noOfBytes = 0; while ((noOfBytes = in.read(b)) != -1) fout.write(b, 0, noOfBytes); in.close(); fout.close(); contents.discard(googleApiClient); } catch (FileNotFoundException e) { // something went wrong, delete the file we were trying to create (new File(localFileToCreate)).delete(); } catch (IOException e) { // something went wrong, delete the file we were trying to create (new File(localFileToCreate)).delete(); } } /** **** Upload any files that are missing remotely ***** */ for (String localFile : arrLocalFiles) { // if the remote folder does not exist, create it. This should only need to be called // once. if (teamPhotosFolder == null) { MetadataChangeSet changeSet = new MetadataChangeSet.Builder().setTitle("" + teamNumber).build(); DriveFolder.DriveFolderResult folderResult = rootFolder.createFolder(googleApiClient, changeSet).await(); teamPhotosFolder = folderResult.getDriveFolder(); } DriveContents contents = null; try { FileInputStream in = new FileInputStream(localFile); // create a new file in Drive. This works a little different than normal file IO it that // you create the file first, // then tell it at the end which folder it's part of. Think of "folders" in drive more // like "tags" or "labels". DriveApi.DriveContentsResult contentResult = Drive.DriveApi.newDriveContents(googleApiClient).await(); contents = contentResult.getDriveContents(); OutputStream out = contents.getOutputStream(); // read bytes from source file and write to destination file byte[] b = new byte[1024]; int noOfBytes = 0; while ((noOfBytes = in.read(b)) != -1) out.write(b, 0, noOfBytes); in.close(); out.close(); } catch (FileNotFoundException e) { // something went wrong, discard the changes to the Drive file if (contents != null) contents.discard(googleApiClient); } catch (IOException e) { // something went wrong, discard the changes to the Drive file if (contents != null) contents.discard(googleApiClient); } if (contents != null) { String[] splitFilename = localFile.split("/"); String filename = splitFilename[splitFilename.length - 1]; MetadataChangeSet changeSet = new MetadataChangeSet.Builder() .setTitle(filename) .setMimeType(URLConnection.guessContentTypeFromName(filename)) .build(); teamPhotosFolder.createFile(googleApiClient, changeSet, contents).await(); } } Log.i( mActivity.getResources().getString(R.string.app_name), "Finished photo sync for team " + teamNumber); googleApiClient.disconnect(); // hand the photos back to the PhotoRequester if (mRequester != null) { // first, get the list of image files listOfFiles = photosDir.listFiles(); ArrayList<Bitmap> arrLocalBitmaps = new ArrayList<Bitmap>(); for (File file : listOfFiles) { // make sure it's an image file Bitmap bitmap = BitmapFactory.decodeFile(file.getPath()); if (bitmap != null) { arrLocalBitmaps.add(bitmap); } // else: if it's not a file, then what is it???? .... skip I guess } Bitmap[] bitmaps = new Bitmap[arrLocalBitmaps.size()]; // TODO: commented out because it crashes the app with the error: // "Only the original thread that created a view hierarchy can touch its views." // This will need a re-jigging - maybe a loop in the PhotoRequester that checks for // updates every // few seconds and re-draws if there has been one. // mRequester.updatePhotos(arrLocalBitmaps.toArray(bitmaps)); } } }