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
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;
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;
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.
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));