22
33// Command accounts demonstrates querying Android device accounts
44// using the accounts package, which wraps android.accounts.AccountManager.
5- // It is built as a c-shared library and packaged into an APK using
6- // the shared apk.mk infrastructure.
75package main
86
97/*
@@ -21,10 +19,9 @@ import (
2119 "unsafe"
2220
2321 "github.com/AndroidGoLab/jni"
22+ "github.com/AndroidGoLab/jni/accounts"
2423 "github.com/AndroidGoLab/jni/capi"
2524 "github.com/AndroidGoLab/jni/exampleui"
26- "github.com/AndroidGoLab/jni/accounts"
27- "github.com/AndroidGoLab/jni/app"
2825)
2926
3027func main () {}
@@ -53,70 +50,79 @@ func goOnNativeWindowCreated(activity *C.ANativeActivity, window *C.ANativeWindo
5350}
5451
5552func run (vm * jni.VM , output * bytes.Buffer ) error {
56- _ , err := getAppContext (vm )
53+ ctx , err := exampleui . GetAppContext (vm )
5754 if err != nil {
5855 return fmt .Errorf ("get context: %w" , err )
5956 }
57+ defer ctx .Close ()
6058
61- // The accounts package wraps android.accounts.AccountManager.
62- // The Manager type provides access to device accounts through
63- // unexported methods (getAccountsRaw, getAccountsByTypeRaw,
64- // getAuthTokenRaw, invalidateAuthTokenRaw) which are intended
65- // to be wrapped by higher-level helpers.
66- //
67- // The Manager struct has exported fields:
68- // VM *jni.VM
69- // Obj *jni.GlobalRef
70- //
71- // Manager is obtained via the static factory AccountManager.get(Context),
72- // exposed as the unexported getManagerRaw method.
73-
74- // Account is a data class with exported fields extracted from
75- // android.accounts.Account Java objects.
76- // Account wraps android.accounts.Account. Its fields (VM, Obj) hold
77- // references to the Java object. Name and Type are accessed via JNI
78- // methods (DescribeContents, Equals, HashCode, etc.).
79- var acct accounts.Account
80- _ = acct
81- fmt .Fprintln (output , "Account type available with DescribeContents, Equals, HashCode methods" )
82-
83- fmt .Fprintln (output , "AccountManager raw methods: getManagerRaw, getAccountsRaw, getAccountsByTypeRaw, getAuthTokenRaw, invalidateAuthTokenRaw" )
59+ mgr , err := accounts .NewAccountManager (ctx )
60+ if err != nil {
61+ return fmt .Errorf ("NewAccountManager: %w" , err )
62+ }
63+ defer mgr .Close ()
8464
85- return nil
86- }
65+ fmt .Fprintln (output , "=== Device Accounts ===" )
8766
88- // getAppContext obtains an Android Context via ActivityThread.currentApplication().
89- func getAppContext (vm * jni.VM ) (* app.Context , error ) {
90- var ctx app.Context
91- ctx .VM = vm
67+ acctArray , err := mgr .GetAccounts ()
68+ if err != nil {
69+ fmt .Fprintf (output , "GetAccounts: %v\n " , err )
70+ return nil
71+ }
9272
93- err := vm .Do (func (env * jni.Env ) error {
94- if err := app .Init (env ); err != nil {
95- return err
73+ var acctCount int32
74+ err = vm .Do (func (env * jni.Env ) error {
75+ if acctArray == nil {
76+ return nil
9677 }
78+ acctCount = env .GetArrayLength ((* jni .Array )(unsafe .Pointer (acctArray )))
79+ return nil
80+ })
81+ if err != nil {
82+ return fmt .Errorf ("get array length: %w" , err )
83+ }
9784
98- atClass , err := env .FindClass ("android/app/ActivityThread" )
85+ fmt .Fprintf (output , "Account count: %d\n " , acctCount )
86+
87+ for i := int32 (0 ); i < acctCount ; i ++ {
88+ acct := accounts.Account {VM : vm }
89+ err := vm .Do (func (env * jni.Env ) error {
90+ elem , err := env .GetObjectArrayElement ((* jni .ObjectArray )(unsafe .Pointer (acctArray )), i )
91+ if err != nil {
92+ return fmt .Errorf ("get element %d: %w" , i , err )
93+ }
94+ acct .Obj = env .NewGlobalRef (elem )
95+ return nil
96+ })
9997 if err != nil {
100- return fmt .Errorf ("find ActivityThread: %w" , err )
98+ fmt .Fprintf (output , " [%d] error: %v\n " , i , err )
99+ continue
101100 }
102101
103- curAppMid , err := env . GetStaticMethodID ( atClass , "currentApplication" , "()Landroid/app/Application;" )
102+ str , err := acct . ToString ( )
104103 if err != nil {
105- return fmt .Errorf ("get currentApplication: %w" , err )
106- }
107- appObj , err := env .CallStaticObjectMethod (atClass , curAppMid )
108- if err != nil {
109- return fmt .Errorf ("call currentApplication: %w" , err )
110- }
111- if appObj == nil || appObj .Ref () == 0 {
112- return fmt .Errorf ("currentApplication returned null" )
104+ fmt .Fprintf (output , " [%d] ToString err: %v\n " , i , err )
105+ } else {
106+ fmt .Fprintf (output , " [%d] %s\n " , i , str )
113107 }
108+ }
114109
115- ctx .Obj = env .NewGlobalRef (appObj )
116- return nil
117- })
110+ authArray , err := mgr .GetAuthenticatorTypes ()
118111 if err != nil {
119- return nil , err
112+ fmt .Fprintf (output , "GetAuthenticatorTypes: %v\n " , err )
113+ return nil
120114 }
121- return & ctx , nil
115+
116+ var authCount int32
117+ _ = vm .Do (func (env * jni.Env ) error {
118+ if authArray == nil {
119+ return nil
120+ }
121+ authCount = env .GetArrayLength ((* jni .Array )(unsafe .Pointer (authArray )))
122+ return nil
123+ })
124+
125+ fmt .Fprintf (output , "\n Authenticator types: %d\n " , authCount )
126+
127+ return nil
122128}
0 commit comments