How to get device email address in Delphi 10

后端 未结 4 1774
执念已碎
执念已碎 2020-12-06 15:37

I\'m trying to get my device email address, I used Java2OP to convert AccountManager class to object pascal. However, I tried to get the email address using the following co

相关标签:
4条回答
  • 2020-12-06 16:11

    getAccountsByType() returns an array of Account objects, not an array of class types. And check for nil pointers.

    Try this instead:

    var
      jAm: JAccountManager;
      accounts: TJavaObjectArray<JAccount>;
      jAcc: JAccount;
    begin
      jAM := TJAccountManager.JavaClass.get(SharedActivityContext);
      if jAM <> nil then begin
        accounts := TJavaObjectArray<JAccount>.Wrap(jAM.getAccountsByType(StringToJString('com.google')));
        if accounts <> nil then begin
          mmLog.Lines.Add('Length Accounts: ' + IntToStr(accounts.Length));
          if accounts.Length > 0 then begin
            jAcc := accounts.Items[0];
            mmLog.Lines.Add(JStringtoString(jAcc.name));
          end else begin
            mmLog.Lines.Add('no accounts available');
          end;
        end;
      end else begin
        mmLog.Lines.Add('no accounts found');
      end;
    else begin
      mmLog.Lines.Add('no account manager available');
    end;
    
    0 讨论(0)
  • 2020-12-06 16:17

    copy {class} function _Getname: JString; cdecl; to JAccount class, then use this code:

    var
      jAm: JAccountManager;
      accounts: TJavaObjectArray<JAccount>;
      jAcc: JAccount;
    begin
      jAM := TJAccountManager.JavaClass.get(SharedActivityContext);
      if jAM <> nil then begin
        accounts := TJavaObjectArray<JAccount>.Wrap(jAM.getAccountsByType(StringToJString('com.google')));
        if accounts <> nil then begin
          mmLog.Lines.Add('Length Accounts: ' + IntToStr(accounts.Length));
          if accounts.Length > 0 then begin
            jAcc := accounts.Items[0];
            mmLog.Lines.Add(JStringtoString(jAcc._Getname));
          end else begin
            mmLog.Lines.Add('no accounts available');
          end;
        end;
      end else begin
        mmLog.Lines.Add('no accounts found');
      end;
    end;
    
    0 讨论(0)
  • 2020-12-06 16:23

    Since there have been some comments about issues using the code snippets I thought it might be helpful to throw in a full unit (albeit containing minimal import definitions) to try and belay the problems and confusion.

    Here is a helper unit that works in Delphi XE8 through to Delphi 10.1 Berlin (I can't check earlier versions, but in principle it should be OK):

    unit AccountEmailsU;
    
    interface
    
    function GetAccountEmails(const AccountType: String): TArray<String>;
    
    implementation
    
    uses
      Androidapi.Helpers,
      Androidapi.Jni,
    {$IF Declared(RTLVersion) and (RTLVersion >= 31)}
      // Delphi 10.1 Berlin adds in full imports for the accounts classes
      Androidapi.JNI.Accounts;
    {$ELSE}
      Androidapi.JNIBridge,
      Androidapi.JNI.App,
      Androidapi.JNI.GraphicsContentViewText,
      Androidapi.JNI.JavaTypes,
      Androidapi.JNI.Os;
    
    type
    // ===== Forward declarations =====
    
      JAccount = interface;//android.accounts.Account
      JAccountManager = interface;//android.accounts.AccountManager
    
    // ===== Interface declarations =====
    
      JAccountClass = interface(JObjectClass)
        ['{94EE6861-F326-489F-8919-E20B39E3D9C1}']
      end;
    
      [JavaSignature('android/accounts/Account')]
      JAccount = interface(JObject)
        ['{71476381-8B6E-471F-9189-9857ECD7508C}']
        function _Getname: JString; cdecl;
        function _Gettype: JString; cdecl;
        property name: JString read _Getname;
        property &type: JString read _Gettype;
      end;
      TJAccount = class(TJavaGenericImport<JAccountClass, JAccount>) end;
    
      JAccountManagerClass = interface(JObjectClass)
        ['{96273844-2D84-47F0-BFD5-14B73402F843}']
        {class} function &get(context: JContext): JAccountManager; cdecl;
      end;
    
      [JavaSignature('android/accounts/AccountManager')]
      JAccountManager = interface(JObject)
        ['{9FA4077B-4628-433C-BAFC-9EB299DA9C98}']
        function getAccountsByType(type_: JString): TJavaObjectArray<JAccount>; cdecl;
      end;
      TJAccountManager = class(TJavaGenericImport<JAccountManagerClass, JAccountManager>) end;
    {$ENDIF}
    
    function GetAccountEmails(const AccountType: String): TArray<String>;
    var
      AccountManager: JAccountManager;
      Accounts: TJavaObjectArray<JAccount>;
      Account: JAccount;
      AccountLoopCounter: Integer;
    begin
    {$IF RTLVersion >= 30}
      AccountManager := TJAccountManager.JavaClass.get(TAndroidHelper.Context);
    {$ELSE}
      AccountManager := TJAccountManager.JavaClass.get(SharedActivityContext);
    {$ENDIF}
      if AccountManager <> nil then
      begin
        Accounts := AccountManager.getAccountsByType(StringToJString(AccountType));
        if Accounts <> nil then
        begin
          SetLength(Result, Accounts.Length);
          for AccountLoopCounter := 0 to Pred(Accounts.Length) do
          begin
            //Account := Accounts.Items[AccountLoopCounter];
            Account := TJAccount.Wrap(Accounts.GetRawItem(AccountLoopCounter));
            Result[AccountLoopCounter] := JStringtoString(Account.name);
          end
        end;
      end;
    end;
    
    procedure RegisterTypes;
    begin
      TRegTypes.RegisterType('AccountEmailsU.JAccount', TypeInfo(AccountEmailsU.JAccount));
      TRegTypes.RegisterType('AccountEmailsU.JAccountManager', TypeInfo(AccountEmailsU.JAccountManager));
    end;
    
    initialization
      RegisterTypes;
    end.
    

    This can be used in a fashion akin to this:

    uses
    {$IF RTLVersion >= 31}
      FMX.DialogService,
    //{$ELSE}
    //  FMX.Dialogs,
    {$ENDIF}
      AccountEmailsU,
      MiscU;
    
    procedure TForm1.btnGetAccountEmailsClick(Sender: TObject);
    const
      AccountType = 'com.google';
    var
      AccountNames: TArray<String>;
      AccountLoopCounter: Integer;
    begin
      if not HasPermission('android.permission.GET_ACCOUNTS') then
    {$IF RTLVersion >= 31}
        TDialogService.MessageDialog('App does not have the GET_ACCOUNTS permission',
          TMsgDlgType.mtError, [TMsgDlgBtn.mbCancel], TMsgDlgBtn.mbCancel, 0, nil)
    {$ELSE}
        MessageDlg('App does not have the GET_ACCOUNTS permission',
          TMsgDlgType.mtError, [TMsgDlgBtn.mbCancel], 0)
    {$ENDIF}
      else
      begin
        AccountNames := GetAccountEmails(AccountType);
        AccountsListBox.Items.Clear;
        for AccountLoopCounter := Low(AccountNames) to High(AccountNames) do
          AccountsListBox.Items.Add(AccountNames[AccountLoopCounter])
      end;
    end;
    

    The permissions checking code comes from this helper unit:

    unit MiscU;
    
    interface
    
    function HasPermission(const Permission: string): Boolean;
    
    implementation
    
    uses
      FMX.Helpers.Android,
      Androidapi.Helpers,
      Androidapi.JNI.JavaTypes,
      Androidapi.JNI.GraphicsContentViewText;
    
    function HasPermission(const Permission: string): Boolean;
    begin
      //Permissions listed at http://d.android.com/reference/android/Manifest.permission.html
    {$IF RTLVersion >= 30}
      Result := TAndroidHelper.Context.checkCallingOrSelfPermission(
    {$ELSE}
      Result := SharedActivityContext.checkCallingOrSelfPermission(
    {$ENDIF}
        StringToJString(Permission)) =
        TJPackageManager.JavaClass.PERMISSION_GRANTED
    end;
    
    end.
    
    0 讨论(0)
  • 2020-12-06 16:33

    You should use the name property of the Account and not asking to convert the object to a string.

    mmLog.Lines.Add(jstringtostring( jAcc.name));
    
    0 讨论(0)
提交回复
热议问题