How can I programmatically remove/clear a linked account from an Android device within Android Settings > Accounts? Is this possible with ADB or Appium, or by some other programmatic method?
Android devices typically keep linked accounts for Google or Facebook on a device settings level, not within a single app's cache. I would like to remove these accounts (especially Facebook, which appears to only have one account per device).
The context for the question is in automated testing.
Removing accounts manually/by hand is not an option.
I'd prefer not to do it via Appium UI automation; even if Appium could solve this problem on one device, different android devices/OS versions have different settings UI, thus UI automation is not a scalable solution.
The best, easiest, and most scalable solution would allow me to do an ADB command which could remove the linked account.
Edit:
Here is an unanswered question on Appium forums asking a similar question: https://discuss.appium.io/t/android-how-to-remove-google-accounts-linked-a-device-on-setting-activity/6920
Linked accounts are stored in the database /data/system_ce/0/accounts_ce.db, to access it you need root access.
In the case if you have root access you can simply remove the entry of the specified account from the database.
I had the same question, and found something to remove ALL accounts.
Take a look at what AuthenticatorDescription types you are getting if you strictly only want to delete e.g. Google Accounts
private void clearAccounts() {
AccountManager manager = AccountManager.get(getApplicationContext());
AuthenticatorDescription[] authTypes = manager.getAuthenticatorTypes();
for (AuthenticatorDescription authDesc : authTypes) {
Account[] accounts = manager.getAccountsByType(authDesc.type);
if (accounts.length == 0) {
continue; // No accounts of this type, continue loop.
}
for (final Account account : accounts) {
manager.removeAccount(account, null, null, null);
}
}
}
Related
Prelude:
The client wants to install EMM for his owner devices. Sometimes the user wants to use the device as work device (only taxi and couriers apps) and sometimes the user wants to use the device as his own (install games, social apps, and his own Google accounts).
Situation:
The client wants to store his gsuite accounts in FRP storage (to have the ability to unlock a phone in case employee leave organization) but doesn't want an employee to unlock the phone after FR entering his personal account credentials.
Example:
I added two work account programmatically (like described here). But after the user gets the phone he entered his personal Gmail account to use Gmail, other apps. How can I programmatically or maybe from DPC app prevents user recover access to the phone using his personal account after Factory Reset?
I found the answer, finally. The link to the documentation.
I need just to create a bundle with google plus ids of accounts that will have the opportunity to recover device after factory reset.
And after that need to send a broadcast to notify the system that these values were changed.
val bundle = Bundle()
// list of recovery accounts
val recoveryAccounts = arrayOf(
"115273111154663031432",
"110369192556268846321",
)
bundle.putStringArray("factoryResetProtectionAdmin", recoveryAccounts)
mAdminComponentName = DeviceAdminReceiver.getComponentName(context)
// set restrictions
mDevicePolicyManager.setApplicationRestrictions(mAdminComponentName, "com.google.android.gms", bundle)
// send broadcast
val broadcastIntent = Intent("com.google.android.gms.auth.FRP_CONFIG_CHANGED")
broadcastIntent.setPackage("com.google.android.gms")
broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
applicationContext.sendBroadcast(broadcastIntent)
Off topic.
To get the id of recovery accounts try this: https://developers.google.com/people/api/rest/v1/people/get?apix=true&apix_params={"resourceName":"people/me","personFields":"metadata"}
Push "Execute" and login with needed account. It'll be shown in "id" field of response.
I've been looking for a solution to this problem for a while (days, not minutes), but it eludes me quite effectively.
Please note that this is NOT a question about starting up the registration procedure. This must happen automatically without any user interaction.
I would like to add a Google account to my custom device (1000's of them). The account will mostly be used to activate Google Play store on the device so that the app can update when newer versions are available.
My existing code (the shortest snippet of those I tried):
AccountManager mgr = AccountManager.get(this);
Account acc = new Account("email#gmail.com", "com.google");
mgr.addAccountExplicitly(acc, "password", new Bundle()));
naturally yields a
java.lang.SecurityException: caller uid 10047 is different than the authenticator's uid
So how would I go about actually achieving this? My device is rooted so that's not an obstacle if it's the only way.
It is not possible to add/create a Google account using addAccountExplicitly(). You can only add accounts for your own services. even your device is rooted because it will rejected by Google web server. For more detail check this link
Warning: this solution doesn't work well. See comments for explanation.
Well, as it turns out, this is not something easily solved. I ended up registering one device, then pulled the users file from it. Location of users file : /data/system/users/0/accounts.db (if there are multiple user profiles on the device, the last directory may differ according to profile in question).
I stored this file into my app's assets (gzipped, make sure the extension is not something.gz because that gets lost during packaging - didn't bother checking out why).
First I check if my user already exists:
AccountManager mgr = AccountManager.get(this);
for (Account acc: mgr.getAccountsByType("com.google")) {
if (acc.name.equalsIgnoreCase("email#gmail.com"))
return;
}
If it does, I just skip the step. Otherwise I unpack the users file and overwrite existing one (using su). I then also do a reboot to make sure changes are registered.
In my project I need to access the Exchange accounts on the device, to change them.
I need to do it programatically , inside my application.
I have searched around but it does not seem that there is a way of doing such a thing.
Please any help or suggestion?
EDIT EDIT
To be more specific i need to:
lists all email accounts on the device and allows the user to change settings for Exchange accounts:
*server address
*server port number
*SSL (on/off)
*accept all SSL certificates (on/off)
*account password
You can't modify the permissions/settings of an another exchange account (it gives you a security error). You only can create your own exchange account witch it will be included in your exchange accounts as yourAppName..
Take a look at AccountManager (http://developer.android.com/reference/android/accounts/AccountManager.html)
You should be able to do something like this:
AccountManager accountManager = AccountManager.get(context);
Account[] accountList = accountManager.getAccounts();
for(Account account : accountList){
accountManager.getUserData(account, AccountManager.KEY_USERDATA);
accountManager.setUserData(account, AccountManager.KEY_USERDATA, "data");
}
Powershell is probably the tool that I would want to use to do this, but from devices it is tricky. Tools like AccountManager should assit with this as under the hood they are probably using Remote Powershell scripting. Alternatives that I can think of are:
Create your own web service that you can execute powershell commands from, and have your app connect to that. This is a good primer that works for Exchange 2010 and 2013: http://forums.asp.net/t/1683553.aspx?Mailbox+creation+in+Exchange+Server+2010+using+ASP+Net+3+5+application
Find a tool to execute remote powershell requests from the device direct. I have not tried this but this looks like a good thread to follow: http://social.technet.microsoft.com/Forums/windowsserver/en-US/bc1b417d-0388-486b-8742-305a48224a92/android-client-for-powershell-remote-scripting?forum=winserverpowershell
I personally already had web services hosted inside the domain that my app was using anyway (data source was in the domain), so I put my mailbox and AD user management service along side those, then the mobile apps made simple calls like CreateUser, EnableMailbox, CreateMailEnabledUser...
I'm trying to find out if the user has Google-Photos (picasa) set to sync on their device. Is there any way to programmatically determine whether sync is turned on for any of the google accounts set up on the user's phone?
Also, is there any way to programmatically turn synching off for Google-Photos? If not, what is the correct Intent to launch an activity directly to the Google account's "Data & Synchronization" screen, so that the user can manual disable sync?
Thanks in advance!
EDIT:
I found some code that is useful, but what is the Authority string for "Google-Photos" (aka Picasa)???
import android.provider.ContactsContract;
AccountManager am = AccountManager.get(this);
Account[] accounts = am.getAccountsByType("com.google");
boolean syncEnabled = ContentResolver.getSyncAutomatically(accounts[0], ContactsContract.AUTHORITY);
There are two case
1) If your device is already synchronize with Google account
Then Account selector will select current login account.Refer this link
2) If your account selector does not return any account that means you are not login with any Google account. So you need to synchronize.Now in this case open your account screen and one account This will help you
I am writing an android application that will start sync for all accounts added under "Account & sync" settings.I am fetching all the added accounts using the following code
AccountManager am = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
Account[]acs = am.getAccounts();
After fetching the account I want to start sync for each account
for(Account ac:acs){
ContentResolver.requestSync(ac,authority,extras);
}
My question is how do i fetch the authority for the retrieved account ?
A far simpler answer is simply to turn off the global sync enabled flag and then turn it back on. Android starts a full sync by defualt in this case.
See ContentResolver.setMasterSyncAutomatically().
Your app will need appropriate permissions in the manifest to be allowed to change that flag.