GPlayServices #1: Save to Google Drive

A little snippet to save a file (or some contents) in Google Drive with the Drive API included in the Google Play Services.

To use the Google Drive API we have to follow these steps:(this blog doesn't cover these topics) : Now we can build our code.

First of all, we have to create an instance of GoogleApiClient using the GoogleApiClient.Builder and implementing the callback interfaces to manage the connection and the authorizations as described in GPlay Service #0.

Our scope is to save a file (an image) choosing a folder in Google Drive.

To choose a folder inside our Google Drive we can use the Drive.DriveApi.newOpenFileActivityBuilder().
This method creates a builder for an Open File activity that allows user selection of a Drive file. Upon completion, the result Intent will contain the DriveId for the selected file.

We can use the OnConnected interface to know when the connect request has successfully completed, setup the Intent to create the builder and enable the Button to save
    @Override
    public void onConnected(Bundle connectionHint) {
        super.onConnected(connectionHint);

        //Enable the save button and intentPicker
        if (intentPicker == null) {
            intentPicker = buildIntent();
        }

        mSave.setEnabled(true);
    }

    private IntentSender buildIntent(){
        return Drive.DriveApi
                .newOpenFileActivityBuilder()
                .setMimeType(new String[]{DriveFolder.MIME_TYPE})
                .build(mGoogleApiClient);
    }
It is important to use the DriveFolder.MIME_TYPE to allow user selection of a Drive folder.
In our example we will use a Button to launch the Folder Picker.
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gdrive);

        //Setup the Save Button
        mSave = (Button) findViewById(R.id.save_to_gdrive);
        mSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    if (mGoogleApiClient!=null && mGoogleApiClient.isConnected()){
                        if (intentPicker==null)
                            intentPicker = buildIntent();
                        //Start the picker to choose a folder
                        startIntentSenderForResult(
                                intentPicker, REQUEST_CODE_PICKER, null, 0, 0, 0);
                        }
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Unable to send intent", e);
                }
            }
        });
        mSave.setEnabled(false);
    }

Clicking the Button the GoogleApiClient will launch the Activity to allow user selection of a Drive folder.

We can retrieve the Folder Drive id using this code:
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_CODE_PICKER:
                intentPicker = null;

                if (resultCode == RESULT_OK) {
                    //Get the folder drive id
                    mFolderDriveId = (DriveId) data.getParcelableExtra(
                            OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);

                    if (mFolderDriveId != null) {
                        //Create the file on GDrive
                        Drive.DriveApi.newContents(mGoogleApiClient)
                                .setResultCallback(creatingFileResult);
                    }
                }
                break;
            default:
                super.onActivityResult(requestCode, resultCode, data);
                break;
        }
    }
Now we can save our bitmap in the selected folder using an asynchronous call implementing a ResultCallback
     final private ResultCallback creatingFileResult = new
            ResultCallback() {
                @Override
                public void onResult(DriveApi.ContentsResult result) {
                    if (!result.getStatus().isSuccess()) {
                        showMessage("Error while trying to create new file contents");
                        return;
                    }

                    DriveFolder folder = Drive.DriveApi.getFolder(mGoogleApiClient, mFolderDriveId);
                    OutputStream outputStream = result.getContents().getOutputStream();

                    Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.sea);
                    ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
                    image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
                    try {
                        outputStream.write(bitmapStream.toByteArray());
                    } catch (IOException e1) {
                        Log.i(TAG, "Unable to write file contents.");
                    }

                    MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                            .setTitle("New file") //Your title
                            .setMimeType("image/jpeg")  //Your mime type
                            .setStarred(false).build();

                    folder.createFile(mGoogleApiClient, changeSet, result.getContents())
                            .setResultCallback(fileCallback);
                }
            };
Of course it is just an example.
Also in this case we can use an asynchronous call to know if our request has successfully completed.
    final private ResultCallback fileCallback = new
            ResultCallback() {
                @Override
                public void onResult(DriveFolder.DriveFileResult result) {
                    if (!result.getStatus().isSuccess()) {
                        showMessage("Error while trying to create the file");
                        return;
                    }

                    showMessage("File saved on Google Drive");
                }
            };
And that's all.

You can get code from GitHub:

Comments

Popular posts from this blog

AntiPattern: freezing a UI with Broadcast Receiver

How to centralize the support libraries dependencies in gradle

NotificationListenerService and kitkat