Sync selected accounts at user defined frequencies - android

I'm developing an android application that Sync selected accounts at user defined frequencies.
AccountManager manager = (AccountManager) getSystemService(ACCOUNT_SERVICE);
Account[] list = manager.getAccounts();
Pattern emailPattern = Patterns.EMAIL_ADDRESS;
for(i=0;i<AcntCount;i++)
for (Account account : list)
if (emailPattern.matcher(account.name).matches())
if(account.name.matches(syncSettings.getString("Account"+i.toString(), null)))
//ContentResolver.addPeriodicSync(account, authority, extras, pollFrequency)
What are the values that should be given in place of authority and extras in the addPeriodicSync().
Do I have to write a sync-adapter for this?

Yes. You have to write a SyncAdapter. addPeriodicSync() is specifically used to tell ContentResolver to cause a SyncAdapter to fire on a timer.
What authority do you need? Well, SyncAdapters work on a (Account,Authority) pair.
The account specifies the specific login -- you might have multiple if you have more than one gmail address, for example.
The Authority tells the kind of data -- For example, with a gmail acocunt, you might be synchronizing... mail, contacts, calendar, finance, etc... So this tells you the type of data and the service that's bound to the account.
The pair together is provided to SyncAdapter -- More specifically you have a bunch of syncAdapters on the system (They define the authorities that are available to sync), and the correct syncadapter is looked up when PeriodicSync fires.
So if you're writing your own app that synchronizes against your own custom server, you'll write a SyncAdapter that knows how to read and store your schema, and you'll define an authority. These are just a string, and it's usually in java-classpath style. -- "com.example.SyncAdapterSample"
Read Why does ContentResolver.requestSync not trigger a sync? for all the steps you need to get a working SyncAdapter. It's definitely the way you want to go. A lot of steps to get it set up, but once the framework is there, it makes your life so much easier.
Now -- Extras. These are just some options for how the periodic sync will be done. You should be fine with the defaults, at first. Then dig into The documents. For example, the extra SYNC_EXTRAS_EXPEDITED indicates that this is a high priority update that should be synced right away -- usually, the scheduler waits a minute or two so that it can batch requests (and save battery, by not having the radio on all the time, but only in concentrated bursts). In general, you shouldn't need to worry about extras until your SyncAdapter gets much more complex than a simple baseline one.

Related

Poll vs Push... which would be better for multiple emails in an app?

I am working on an Android APP that will handle multiple email accounts, POP3 and IMAP. The current APP, to check for email, you open the APP and click on an update feature. That logs into each email account, and checks for any new mail. Although this works, we need a more efficient, and timely check for new messages.
At first I thought PUSH was the way to go but from what I have read on here, that may not be ideal... especially with multiple IMAP accounts. If I understand right, it keeps each IMAP connection open long-term which could cause some other issues and not sure I could even use it with POP3 accounts.
I looked into POLL as an alternative but that too has potential issues. That involves how frequent it fires up and does the account "checks", the amount of time that takes, and how that all effects battery life. In addition, there appears to be several different "ways" to schedule the POLL option (AlarmManager, JobScheduler, and SyncAdapter)... and I assume one might be better than the other... especially with new version of Android that let you "quiet" your device at certain times of the day.
So the question is, based on what we are looking to do, which is the better way to handle this capability? I am leaning towards PUSH (which format...still unsure), but don't want to waste hours of time to find out that I went down the wrong path.
Thanks ahead for any advice.
IMAP supports IDLE Command in which client acts as passive entity depending/relying upon the server to notify arrival of new mails in account. But as you correctly figured out that it will keep connection open and other issues of rebuilding the connection if it gets disturbed due to any possible reason.
POP do not provide such passive capability to clients. Clients have to pull the mails from server.
From my experience, total synchronization of account on client side is not a problem but it requires too many things to be taken care of like parsing the mail content, maintaining the active list of mails in an account's folder, etc.
[1] Very simple synchronization mechanism would be to simply show the MailList and whenever a message is clicked upon then dynamically load the content of mail.
MailList = Sorted order of Mail Entries in an account's folder.
Single Mail Entry = Sender + Mail Subject + Mail Date & Time + Mail Size
This method of showing MailList initially and fetching the mail content on demand can be achieved via both:
IMAP (FETCH Subject, INTERNALDATE, Sender, Size) and
POP (TOP n m {TOP is a POP command which can fetch m number of lines of nth mail's body along with complete MailHeaderSection of nth mail}). Afterwards MailHeaderSection can be parsed and MailList can be constructed.
[2] Simply fetch the complete mail and store accordingly. Now, Parse it on demand and show it to user. This is also readily supported in both:
IMAP (FETCH BODY.PEEK[])
POP (RETR n)
I like this method since its simple.
Both the above methods are working as if client is active entity (pulling mails on demand).

how to retrieve information about web services

I have been working on this project for months and I am getting desperate.
I have done research and relied on papers that talked about the user-provider-uddi architecture, so my purpose was the following:
through a mobile app, the user would write a keyword of needed web services, the query and the user's and device profile would both be sent to a middleware. Now the middleware is supposed to get a list of services of the same category as the keyword and compare the web services information to the user and device profile.
For example: it will check the required cpu, memory, screen size, language, location where it works and type of display (graphic/text) and compare it to the device specifications and user's preferences to select the best services.
Now my problem is:
I can't find any public repository (all those mentioned in other posts do not exist anymore)
assuming that I can use an interface (such as JAXR) to get services by category, how can I get the context-related information about services (cpu/memory requirements, language, location, display etc...). would that be possible through JAXR ? Is there a document that describes this about Web services (just like wsdl describe functions?)
what is the common was used to search for web services from a mobile nowadays ?
I know the question is somehow general, but I really worked a lot on this and I'm stuck. If there are people who specialize in the domain, please let me know your opinion. I would like some practical answers that can be implemented.
There are still a few public repositories out there (e.g., Service Repository). It is true that most of the web services you will find are not available anymore, but you can create your own service repository and deploy it either locally or somewhere in the cloud. It is basically just a hash map (service id mapped to a service uri?) and you can use any database to store the data.
Context information usually comes in different types. You have user context, service context, system context, environment context. Usually this information is embedded in the service response messages to the service consumer. Anything that can store data can be used to store this context. It's basically just data. Also, it can be collected when the request comes, but it will introduce a certain delay when serving the request. A proactive approach should be considered here.
This is very general. Depends on the type of service you're interested in. I believe the common approach to query a cloud based registry is the standard.

How safe is AccountManager for storing app state data (like Pro status)?

I have inherited an app which comes as a free version, and Pro monthly subscription is bought via in-app items. The Pro status (a simple string "pro_status") is saved inside the AccountManager (package android.accounts).
//AccountManager initiated
AccountManager mAccountManager = AccountManager.get(this);
//fetch accounts which correspond to our package name
Account[] accounts = mAccountManager.getAccountsByType(getString(R.string.account_type));
//save Pro status inside the AccountManager
mAccountManager.setUserData(mAccount, "is_pro", "" + info.isPro());
The app suffers from a strange bug that it forgets the Pro state randomly, either when you close the app or during the work.
Is this a good way to store Pro status? Could AccountManager be the reason why the app loses the idea of a Pro status?
I usually use either a database or SharedPreferences to store such data (besides storing it on the remote API), so I need a help from someone who used his app in the same way.
Usually the people playing with the setting "pro" status will be the one with rooted devices. Anyways the data stored in the account manager is visible to such users.
So, for such a use case, even account manager is not safe. Though other apps (with different UID) cannot access this data.
Also keep in mind that the user can delete the account from the settings which might be the reason for your settings going away.
My advice would be save this info in shared pref in encrypted form??
In all phones,there is a specific User Database which stores information regarding your accounts.
Is this a good way to store Pro status?
I cannot answer that however I can give you answer to related questions
Is it modifiable?
There are 2 ways of accessing this data, viz
The user explicitly gives permission to an application to read
account details for that particular account. This list of apps
which can access the details for this account are stored based on
PIDs,which cannot be same for different apps. check setUserData
and AUTHENTICATE_ACCOUNTS permission
This database can be accessed(and modified ) on a rooted device.
Can a user manually delete this data?
-Yes,He can delete the account from the device itself.It is his device and he can modify any account details on it too.
In my experiece,the Acccount Manager API is very temperamental, and prone to change which can break your code if it is not used in the way that it was intended to be i.e. store User Account details in centralised database.
You should look into the approach and comments(but not the answer) of this question
.
I agree with the shared preferences approach too.

Is it possible to turn on synch in Android Account

I'm working on an application that will allow a user to turn on/off synching for their exchange email account.
I am able to get the exchange account using:
Account[] accs = AccountManager.get(this).getAccountsByType("com.htc.android.mail.eas");
but the Account API doesn't seem to offer what I'm looking for. I have also found ContactsContract.Settings database table which stores synch data, but I'm not that sure where to start with that.
Any ideas?
The ContentResolver contains the API you are looking for.
Check out the "setIsSyncable" method.

Handling login and remember me with the AccountManager

I've integrated android's account management in my application and I can manage accounts from the Accounts & Sync settings.
I want to have the classic login activity that forwards the user to his home activity on successful login, having the option to remember the user's password. However, the AccountAuthenticatorActivity must return its result to the AccountManager with the credentials and the rest of the account information, calling an explicit finish() and returning the intent.
How can I give the AccountManager the info it needs without having to finish() my login activity?
AccountManager is not meant to be called by an interactive application, but rather by a Sync Adapter. (A great tutorial is "Did You Win Yet? » Writing an Android Sync Provider" Part 1 and Part 2 which gives great code examples but doesn't do as great a job of explaining the data flow.) It's like this:
You develop a ContentProvider which wraps a database. You build a SyncAdapter (this is a background Service) to connect to a server and fetch data and sync the ContentProvider to match the server. Then, your UI queries to the ContentProvider to show the fetched data. There are some methods to directly query for specific information as well, if you want to search and cache results for example. See Developing RESTful Android Apps for a nice hour-long session on how the data model should look. They give three architecture examples, starting from a "naïve" implementation then progressing to the proper SyncAdapter model.
As for authentication itself, the way SyncAdapter uses the AccountManager is to obtain an authentication token. This is a (often) a big hexidecimal value, that is passed as part of the HTML headers in lieu of a username/password pair. Think of it as a one-session unique key. Posession of the key is proof of authentication, and they expire periodically. When they expire, you reauthenticate and fetch a new one. SyncAdapater asks AccountManager for an auth token for a specific account-type / username combination. AccountManager auths with the server (asking the user for a new password if necessary due to change) and returns the token to the SyncAdapter, which uses it from then on.
If this model isn't appropriate for your application, you need to manually handle login/logout in your app code instead. Kind of a pain, I know.
#jcwenger That is not entirely correct. You can use the AccountManager from an interactive application as well. For example, you can add accounts without invoking the account manager interface by using AccountManager's addAccountExplicitly() method.
On the "Did You Win Yet?" article you can clearly see that the account manager is invoked from the application's own Activity. This is useful if the application has its own account management interface.
My version of the 'classic flow' using AccountManager:
I use my AuthenticatorActivity both for the normal case where it's used via. Accounts & Sync Settings, but I also open it out for use by applications that rely upon the same Accounts.
I have a separate apk with the Authenticator implemented and other apps (separate apks) that rely upon these Accounts.
Cases handled:
the normal case: the user adds/authenticates via. Accounts & Sync (as per the Android sample project)
handle authentication requests from external apps:
How? I provide an intent filter in the Authenticator app's Manifest so other apps can instantiate the AuthenticatorActivity via. startActivityForResult (they must include an intent extra that indicates who they are (their app's package)). In the AuthenticatorActivity I detect this case and refrain from calling setAccountAuthenticatorResult when the authentication process has come to a end because I reserved it's use for the normal case above. The user enters their credentials and presses Sign In: AccountManger is checked for a matching account and if matched I
persist that Account's username as the active user for the calling app's package. I then return an intent to the calling app via. setResult indicating success, the username and account type. In the case where the Account didn't exist I go through the process that the normal case goes through, i.e. calling addAccountExplicitly and then set the active user and then as before calling setResult and finish.
Hope this helps someone.

Categories

Resources