Search code examples
c#androidgoogle-apixamarin.androidgoogle-drive-android-api

Android.Gms.Drive Download File Assistance


I am creating an app on android (potentially expanding to IOS, but focussing on android first) that, as a feature uploads the users saved data for the app to Google Drive and can also download it.

I am using the Android.Gms.Drive api to achieve this as is suggested by Google dev page. I have gotten to the point where the user can log in and out, as well as upload the saved file, but I cannot figure out how to download a file.

I can find the Metadata for the file I want to download I am uncertain about how to use this to open the file.

Here is the code I used to connect, it is cobbled together from some examples so I am not sure if I did it right

namespace TestApp.Droid
{
    [Activity(Label = "TestApp", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    const string TAG = "MainActivity";

    const int RC_SIGN_IN = 9001;
    GoogleApiClient mGoogleApiClient;
    protected override void OnCreate(Bundle bundle)
    {

       base.OnCreate(bundle);
        // [START configure_signin]
        // Configure sign-in to request the user's ID, email address, and basic
        // profile. ID and basic profile are included in DEFAULT_SIGN_IN.
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DefaultSignIn)    
            .RequestEmail()
            .RequestScopes(new Scope(Constants.scopes))
            .RequestScopes(DriveClass.ScopeFile)
            .RequestScopes(DriveClass.ScopeAppfolder)
             .Build();

        // [END configure_signin]

        // [START build_client]
        // Build a GoogleApiClient with access to the Google Sign-In API and the
        // options specified by gso.
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .AddApi(Auth.GOOGLE_SIGN_IN_API,gso)
                .AddApi(DriveClass.API)
              .AddOnConnectionFailedListener(OnConnectionFailed)
                .Build();
        if (!mGoogleApiClient.IsConnected) { 
            mGoogleApiClient.Connect(GoogleApiClient.SignInModeOptional);
     }
    // [END build_client]
    global::Xamarin.Forms.Forms.Init(this, bundle);
        LoadApplication(new App());
    }
    protected override void OnStart()
    {
        base.OnStart();

       var opr = Auth.GoogleSignInApi.SilentSignIn(mGoogleApiClient);
        if (opr.IsDone)
        {

            var result = opr.Get() as GoogleSignInResult;
            HandleSignInResult(result);
        }
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        if (requestCode == RC_SIGN_IN)
        {
            var result = Auth.GoogleSignInApi.GetSignInResultFromIntent(data);
            HandleSignInResult(result);
        }
    }

    public void HandleSignInResult(GoogleSignInResult result)
    {
        if (result.IsSuccess)
        {
            // Signed in successfully, show authenticated UI.
            var acct = result.SignInAccount;
            if (!mGoogleApiClient.IsConnected)
            {
                mGoogleApiClient.Connect(GoogleApiClient.SignInModeOptional);
            }
        }
        else {
            GoogleInfo.GetInstance().Result = result.Status.ToString(); ;
        }
    }

    public void SignIn()
    {
        var signInIntent = Auth.GoogleSignInApi.GetSignInIntent(mGoogleApiClient);
        StartActivityForResult(signInIntent, RC_SIGN_IN);
    }

    public void SignOut()
    {
       Auth.GoogleSignInApi.SignOut(mGoogleApiClient);
    }

    void RevokeAccess()
    {
        Auth.GoogleSignInApi.RevokeAccess(mGoogleApiClient);
    }

    protected override void OnStop()
    {
        base.OnStop();
        mGoogleApiClient.Disconnect();
    }
}

}

This is what i used to get the metadata

  DriveClass.DriveApi.GetRootFolder(mGoogleApiClient).ListChildrenAsync(mGoogleApiClient);

Which returns all of the data correctly.

Any help would be appreciated. Thankyou in advance


Solution

  • Never mind I found a solution.

            IDriveFile file = DriveClass.DriveApi.GetFile(GoogleInfo.GetInstance().SignInApi, driveID);
            file.GetMetadata(mGoogleApiClient).SetResultCallback(metadataRetrievedCallback());
            Task.Run(() =>
            {
    
                var driveContentsResult = file.Open(mGoogleApiClient,
                    DriveFile.ModeReadOnly, null).Await();
    
                IDriveContents driveContents = driveContentsResult.JavaCast<IDriveApiDriveContentsResult>().DriveContents;
    
                Stream inputstream = driveContents.InputStream;
    
                byte[] buffer = new byte[16 * 1024];
                int read;
                MemoryStream output = new MemoryStream();
    
                while ((read = inputstream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    output.Write(buffer, 0, read);
                }