Search code examples
c#xamarin.android

Google Drive ApI V3 Migration for Xamrin.Android


Please let me know how to migrate to Google Drive API v2 or V3. I found all the answers for the migration related to java.I could't find the equivalent xamarin nuget package for the Google Drive API v2 or V3.

I have tried with this Xamarin.GooglePlayServices.Drive nuget package but in this all the drive api's are depricated.

Can anyone tried google drive integration in xamarin.Please help me.This is my try

    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DefaultSignIn)
                .RequestEmail()
                .Build();

    var mGoogleApiClient = new GoogleApiClient.Builder(this)
                .EnableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .AddApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .Build();


     MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
            .SetTitle(_backupFolderName)
            .Build();
        IDriveFolderDriveFolderResult result;
        try
        {
            result = await DriveClass.DriveApi.GetRootFolder(_googleApiClient)
                .CreateFolderAsync(_googleApiClient, changeSet);
        }
        catch (Exception)
        {
            return null;
        }

Solution

  • I couldn't find any nuget package for google drive which support Xamarin and OAuth authentication. So I found the way to do it in using Http Client Rest API

    Please follow the below steps

    1. Create OAuth Client id using Google Developer Console
    2. Use Client Id along with other information like redirect

      public class GoogleAuthenticator : OAuth2Authenticator
      {
      public static OAuth2Authenticator Auth;
      
      public GoogleAuthenticator(string clientId, string scope, Uri authorizeUrl, Uri redirectUrl,
          GetUsernameAsyncFunc getUsernameAsync = null, bool isUsingNativeUi = false) : base(clientId, scope,
          authorizeUrl, redirectUrl, getUsernameAsync, isUsingNativeUi)
      {
          Auth = new OAuth2Authenticator(clientId, string.Empty, scope,
              authorizeUrl,
              redirectUrl,
              new Uri(GoogleDriveConfig.AccessTokenUri),
              null, true);
      
          Auth.Completed += OnAuthenticationCompleted;
          Auth.Error += OnAuthenticationFailed;
      }
      
      public void OnAuthenticationCompleted(object sender,AuthenticatorCompletedEventArgs e)
      {
          if (e.IsAuthenticated)
          {
              AuthenticationCompleted?.Invoke(e.Account.Properties["access_token"],
                  e.Account.Properties["refresh_token"], e.Account.Properties["expires_in"]);
          }
      
      }
      
      public void OnAuthenticationFailed(object sender, AuthenticatorErrorEventArgs e)
      {
      
      }
      
    3. Launch browser

      public void SignInToDrive(Activity context)
        {
          Intent loginUi = Auth.GetUI(context);
      
          CustomTabsConfiguration.IsShowTitleUsed = false;
          CustomTabsConfiguration.IsActionButtonUsed = false;
          context.StartActivity(loginUi);
        }
      
    4. Create GoogleAuthInterceptor activity

        [Activity(Label = "GoogleAuthInterceptor")] 
        [  IntentFilter ( actions: new[] 
        {Intent.ActionView}, 
         Categories = new[] { Intent.CategoryDefault, 
        Intent.CategoryBrowsable }, 
        DataSchemes = new[] {"YOUR PACKAGE NAME"}, DataPaths = new[] { "/oauth2redirect" 
         } ) ]
      
        public class GoogleAuthInterceptor : Activity
       {
         protected override void OnCreate(Bundle savedInstanceState)
        {
          base.OnCreate(savedInstanceState);
          Uri uriAndroid = Intent.Data;
      
          System.Uri uri = new System.Uri(uriAndroid.ToString());
      
              var intent = new Intent(ApplicationContext, typeof(MainActivity));
              intent.SetFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
              StartActivity(intent);
      
          GoogleAuthenticator.Auth.OnPageLoading(uri);
      
          Finish();
          return;
      }
      }
      
    5. Upload file to Google Drive

      This base address is for all the below google drive API's

        HttpClient _httpClient = httpClient ?? new HttpClient
          {
              BaseAddress = new Uri(),
      
          };
      
      private async Task<HttpResponseMessage> CreateResumableSession(string accessToken, string fileName, long fileSize, string folderId)
      {
      
          var sessionRequest = new 
          HttpRequestMessage(HttpMethod.Post,"upload/drive/v3/files?uploadType=resumable");
          sessionRequest.Headers.Add("Authorization", "Bearer " + accessToken);
          sessionRequest.Headers.Add("X-Upload-Content-Type", "*/*");
          sessionRequest.Headers.Add("X-Upload-Content-Length", fileSize.ToString());
      
          string body = "{\"name\": \"" + fileName + "\", \"parents\": [\"" + folderId + "\"]}";
          sessionRequest.Content = new StringContent(body);
          sessionRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        using (var sessionResponse = await _httpClient.SendAsync(sessionRequest) )
          {
              return sessionResponse;
          };
      
    6. Update file in Google Drive

      private async Task<bool> UpdateFile(string accessToken,string fileId,long fileSize,Stream stream)
      {
         HttpRequestMessage sessionRequest = new HttpRequestMessage(new HttpMethod("PATCH"), "upload/drive/v3/files/" + $"{fileId}");
          sessionRequest.Headers.Add("Authorization", "Bearer " + accessToken);
          sessionRequest.Headers.Add("X-Upload-Content-Type", "*/*");
          sessionRequest.Headers.Add("X-Upload-Content-Length", fileSize.ToString());
          sessionRequest.Content = new StreamContent(stream);
          sessionRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("*/*");
      
          using (var response = await _httpClient.SendAsync(sessionRequest))
          {
              return response.IsSuccessStatusCode;
          }
      }
      
    7. Download File

        public async Task<Stream> DownloadFile(string accessToken, string fileId)
      {
          var request = new HttpRequestMessage(HttpMethod.Get,"drive/v3/files"+ $"/{fileId}" + "?fields=*&alt=media");
          request.Headers.Add("Authorization", "Bearer " + accessToken);
      
          var response = await _httpClient.SendAsync(request);
      
          if (response.IsSuccessStatusCode)
          {
              var contents = await response.Content.ReadAsStreamAsync();
              return contents;
          }
      
          return null; 
      }
      
    8. Get All the Files

      public  async Task<GoogleDriveItem> GetFiles(string folderId, string accessToken)
      {  
          var request = new HttpRequestMessage(HttpMethod.Get,
              "drive/v3/files" +"?q=parents%20%3D%20'" +
              $"{folderId}" +
              "'%20and%20trashed%20%3D%20false&fields=files(id%2Cname%2Ctrashed%2CmodifiedTime%2Cparents)");
          request.Headers.Add("Authorization", "Bearer " + accessToken);
          request.Headers.Add("Accept", "application/json");
          request.Headers.CacheControl = new CacheControlHeaderValue() { NoCache = true 
          };
      
          using (var response = await _httpClient.SendAsync(request))
          {
              var content = await response.Content.ReadAsStringAsync();
              return (JsonConvert.DeserializeObject<GoogleDriveItem>(content));
          }
      }