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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…