将 Google Drive API 与 XamarinForms 结合使用

问题描述 投票:0回答:1

欢迎大家

第一:

我使用了这个示例:“https://github.com/stevenchang0529/XamarinGoogleDriveRest” 这是一个解释如何将 Google Drive API 与 XamrinForms 结合使用的项目,顺便说一下,感谢 Steven Chang。

它工作正常,但每次我想将文件上传到Google Drive时都要求登录帐户,如何才能使其在第一次输入后保存登录数据。

第二: 如何让用户从弹出窗口中选择他的帐户“如下图所示”,而不是使用 Web Authenticator Native Browser:

项目中使用的ViewModel类:

public class MainViewModel
    {
        private string scope = "https://www.googleapis.com/auth/drive.file";
        private string clientId = "clientId here";
        private string redirectUrl = "url:/oauth2redirect";

        

        public ICommand OnGoogleDrive { get;  set; }
        public MainViewModel()
        {
            var auth = new OAuth2Authenticator(
              this.clientId,
              string.Empty,
              scope,
              new Uri("https://accounts.google.com/o/oauth2/v2/auth"),
              new Uri(redirectUrl),
              new Uri("https://www.googleapis.com/oauth2/v4/token"),
              isUsingNativeUI: true);

            AuthenticatorHelper.OAuth2Authenticator = auth;
            auth.Completed +=async  (sender, e) =>
            {
                if (e.IsAuthenticated)
                {

                    var initializer = new GoogleAuthorizationCodeFlow.Initializer
                    {
                        ClientSecrets = new Google.Apis.Auth.OAuth2.ClientSecrets()
                        {
                            ClientId = clientId
                        }
                    };

                    
                    initializer.Scopes = new[] { scope };
                    initializer.DataStore = new FileDataStore("Google.Apis.Auth");
                    var flow = new GoogleAuthorizationCodeFlow(initializer);
                    var user = "DriveTest";

                    var token = new TokenResponse()
                    {
                         AccessToken=e.Account.Properties["access_token"],
                         ExpiresInSeconds=Convert.ToInt64( e.Account.Properties["expires_in"]),
                         RefreshToken=e.Account.Properties["refresh_token"],
                         Scope=e.Account.Properties["scope"],
                         TokenType=e.Account.Properties["token_type"]
                    };

                    UserCredential userCredential = new UserCredential(flow, user, token);
                    var driveService = new DriveService(new BaseClientService.Initializer()
                    {
                        HttpClientInitializer = userCredential,
                        ApplicationName = "Quickstart",
                    });

                    //test google drive
                    DriveServiceHelper helper = new DriveServiceHelper(driveService);
                    var id = await helper.CreateFile();
                    await helper.SaveFile(id, "test", "test save content");
                    var content = await helper.ReadFile(id);
                }
            };

            auth.Error += (sender, e) =>
            {

            };

            this.OnGoogleDrive = new Command(() =>
              {
                  var presenter = new OAuthLoginPresenter();
                  presenter.Login(auth);
              });
        }
    }

    public static class AuthenticatorHelper
    {
        public static OAuth2Authenticator OAuth2Authenticator { get; set; }
    }
c# xamarin xamarin.forms xamarin.android google-drive-api
1个回答
0
投票

即使使用 Xamarin Forms,它也不会 100% 像您在 iOS 设备上的图像。我认为这是一种让 iOS 和 Android 平台都变得相似的方法。

这是一些示例代码。

共享

主页.xaml

此按钮仅在用户未登录时可见。

...
<Button Text="Google Login" 
Command="{Binding GoogleLoginCommand}"
IsVisible="{Binding IsLogedIn, Converter={StaticResource InvertBooleanConverter}}"/>
...

InvertBooleanConverter.cs 当 IsLogedIn 为 True 时,此转换器返回 false;当 IsLogedIn 为 false 时,此转换器返回 true。

public class InvertBooleanConverter : IValueConverter {
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      return !(bool)value;
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   {
      return !(bool)value;
   }
}

型号 GoogleUser.cs

 public class GoogleUser
 {
     public string Name { get; set; }
     public string Email { get; set; }
     public Uri Picture { get; set; }
 }

视图模型

...
public class MainPageViewModel {
   private readonly IGoogleManager _googleManager;

   public DelegateCommand GoogleLoginCommand { get; set; }

   private bool _isLogedIn;
   public bool IsLogedIn
   {
      get { return _isLogedIn; }
      set { _isLogedIn = value; }
   }

   private GoogleUser _googleUser;
   public GoogleUser GoogleUser
   {
      get { return _googleUser; }
      set { _googleUser = value; }
   }

   ...

   public MainPageViewModel(IGoogleManager googleManager){ //Without IoC
       _googleManager = googleManager;
       IsLogedIn = false;
       GoogleLoginCommand = new DelegateCommand(GoogleLogin);         
   }
   
   private void GoogleLogin()
   {
       _googleManager.Login(OnLoginComplete);
   }

   private void OnLoginComplete(GoogleUser googleUser, string message)
   {
       if (googleUser != null){
           GoogleUser = googleUser;
           IsLogedIn = true;
           //Your code after login
       } else {
            //Error
       }
   }
...

每个设备的接口

public interface IGoogleManager
{
   void Login(Action<GoogleUser, string> OnLoginComplete);
   void Logout();
}

iOS

您的项目名称.ios

  1. 下载 GoogleService-info.plist 文件并将其添加到您的 Xamarin.iOS 文件夹。
  2. 打开 GoogleService-info.plist 并复制 REVERSED_CLIENT_ID 值
  3. 打开 info.plist 文件,转到“高级”选项卡,创建一个具有编辑器角色的新 URL,并将其粘贴到“URL 方案”字段中。

AppDelegate.cs 将此代码添加到 AppDelegate 类

...
var googleServiceDictionary = NSDictionary.FromFile("GoogleService-Info.plist");
SignIn.SharedInstance.ClientID = googleServiceDictionary["CLIENT_ID"].ToString();
...

GoogleManager.cs

public class GoogleManager : NSObject, IGoogleManager, ISignInDelegate, ISignInUIDelegate
    {
        private Action<GoogleNativeLogin.Models.GoogleUser, string> _onLoginComplete;
        private UIViewController _viewController { get; set; }

        public GoogleManager()
        {
            SignIn.SharedInstance.UIDelegate = this;
            SignIn.SharedInstance.Delegate = this;
        }

        public void Login(Action<GoogleNativeLogin.Models.GoogleUser, string> OnLoginComplete)
        {
            _onLoginComplete = OnLoginComplete;

            var window = UIApplication.SharedApplication.KeyWindow;
            var vc = window.RootViewController;
            while (vc.PresentedViewController != null)
            {
                vc = vc.PresentedViewController;
            }

            _viewController = vc;

            SignIn.SharedInstance.SignInUser();
        }

        public void Logout()
        {
            SignIn.SharedInstance.SignOutUser();
        }

        public void DidSignIn(SignIn signIn, Google.SignIn.GoogleUser user, NSError error)
        {

            if (user != null && error == null)
                _onLoginComplete?.Invoke(new GoogleNativeLogin.Models.GoogleUser()
                {
                    Name = user.Profile.Name,
                    Email = user.Profile.Email,
                    Picture = user.Profile.HasImage ? new Uri(user.Profile.GetImageUrl(500).ToString()) : new Uri(string.Empty)
                }, string.Empty);
            else
                _onLoginComplete?.Invoke(null, error.LocalizedDescription);
        }

        [Export("signIn:didDisconnectWithUser:withError:")]
        public void DidDisconnect(SignIn signIn, GoogleUser user, NSError error)
        {
            // When the user disconnects from app here
        }

        [Export("signInWillDispatch:error:")]
        public void WillDispatch(SignIn signIn, NSError error)
        {
            //myActivityIndicator.StopAnimating();
        }

        [Export("signIn:presentViewController:")]
        public void PresentViewController(SignIn signIn, UIViewController viewController)
        {
            _viewController?.PresentViewController(viewController, true, null);
        }

        [Export("signIn:dismissViewController:")]
        public void DismissViewController(SignIn signIn, UIViewController viewController)
        {
            _viewController?.DismissViewController(true, null);
        }
    }

安卓

MainActivity.cs 将此代码添加到 MainActivity

...
protected override void OnActivityResult(int requestCode, Result resultCode, Android.Content.Intent data)
{
   base.OnActivityResult(requestCode, resultCode, data);

   if (requestCode == 1)
   {
       GoogleSignInResult result = Auth.GoogleSignInApi.GetSignInResultFromIntent(data);
        GoogleManager.Instance.OnAuthCompleted(result);
   }
}
...

Google 管理器

public class GoogleManager : Java.Lang.Object, IGoogleManager, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener
{
   public Action<GoogleUser, string> _onLoginComplete;
   public static GoogleApiClient _googleApiClient { get; set; }
   public static GoogleManager Instance { get; private set; }

   public GoogleManager()
   {
      Instance = this;
      GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DefaultSignIn)
                                                             .RequestEmail()
                                                             .Build();

      _googleApiClient = new 
GoogleApiClient.Builder(((MainActivity)Forms.Context).ApplicationContext)
                .AddConnectionCallbacks(this)
                .AddOnConnectionFailedListener(this)
                .AddApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .AddScope(new Scope(Scopes.Profile))
                .Build();
   }

   public void Login(Action<GoogleUser, string> onLoginComplete)
   {
      _onLoginComplete = onLoginComplete;
      Intent signInIntent = Auth.GoogleSignInApi.GetSignInIntent(_googleApiClient);
      ((MainActivity)Forms.Context).StartActivityForResult(signInIntent, 1);
          _googleApiClient.Connect();
   }

   public void Logout()
   {
        _googleApiClient.Disconnect();
   }

   public void OnAuthCompleted(GoogleSignInResult result)
   {
      if (result.IsSuccess)
      {
          GoogleSignInAccount accountt = result.SignInAccount;
          _onLoginComplete?.Invoke(new GoogleUser(){
                   Name = accountt.DisplayName,
                   Email = accountt.Email,
                   Picture = new Uri((accountt.PhotoUrl != null ? $ {accountt.PhotoUrl}" : $"//YOUR_PLACE_HOLDER_IMAGE.jpg//"))}, string.Empty);
        } else {
          _onLoginComplete?.Invoke(null, "An error occured!");
        }
    }

    public void OnConnected(Bundle connectionHint)
    {

    }

    public void OnConnectionSuspended(int cause)
    {
        _onLoginComplete?.Invoke(null, "Canceled!");
    }

    public void OnConnectionFailed(ConnectionResult result)
    {
        _onLoginComplete?.Invoke(null, result.ErrorMessage);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.