I am planning on storing a unique identifier after a user logs in for the first time on an Android and Apple app. This will make sure that the user can only access data from one device if they try to login through another device as I will flag then as having access. I will save this unique identifier in the devices preferences and use it for requests to get this private data.
With that being said I know the preferences can be deleted or removed. This piece of data isnt needed long term and in emergencies we can reset the users account back as if they never got access yet like for a factory reset or deleted app.
My question is, are there any issues with this? These arent developers so somehow getting access to the user preferences to find that unique identifier and using it elsewhere shouldnt be an issue.
for IOS:
You shouldn't concern your self with that cause there is no need to store the identifiers to user prefs (and it is not a good practice).
You just use:
[[[UIDevice currentDevice] identifierForVendor] UUIDString];
It will return the same value as long as it is called from the same device and same vendor. This is explained in:
http://www.doubleencore.com/2013/04/unique-identifiers/
Related
I'm currently working on an android application that fetches information in a webservice. Those informations are related to a user ( who has a numeric user ID ).
So basically, I do Volley requests on URLs like this one :
http://api.mydomain/user/items with a POST parameter which is the userID I want to retrieve items.
When the user first log in to my app, I actually store his user ID in the Shared Preferences. This is useful for two things :
I can access his ID from anywhere in my application and therefore do Volley request with the current user ID.
I also use it on the application Splashscreen ( I check if there is this value in the shared preferences file and if so, he doesnt have to log in again and he's redirected to the application main activity ).
When the user disconnects from the application, I clear the Shared Preferences file, so he will have to log in again next time he open the app.
So here are my problems :
If a rooted user open the shared preferences file, he will be able to change the user ID, and so his identity.
If i keep this operating mode, I can't store user settings preferences ( Enable notifications etc.. ), which is the purpose of the shared preferences file ( I believe ), because i clear it when user disconnects in order to ask him to log-in again next time.
So, as you may think, I have the feeling that it's not the right thing to do..
What is the best pratice to do what i want to do ?
Keep some kind of "session", to avoid the user having to reconnect each time he launch the app.
Store his user ID in a secure manner, to prevent a malicious user to change it.
Is there a way to encrypt those critical data ? Maybe shouldn't I use a numeric ID, but rather some kind of encrypted key, to make it more difficult to change ?
Are SharedPreferences really used to store user's settings ( Should'nt I rather store it in the database ? )
Thank you in advance for helping me and sorry for bad english.
SharePreferences are used to store such information. I store the Auth token in sharedPref in one of my apps. Yes, if user has rooted the phone, the sharedpreference xml becomes directly accessible but that's something that user has to take care off (since rooting is normally not advisable and if rooted don't handover the phone to a programmer!)
Coming to your scenario, you are deleting the shared preference on app close (disconnect). Seems like you are simply using the shared preference in one app life cycle and not the entire lifecycle (from install to uninstall). You can be better off by using a singleton class here. Singleton class will have one instance per life cycle and you can set the userId and get it from anywhere in the applifecycle!! :
Class mySingletonClass{
private String userID;
privat static mySingletonClass instance;
public static getInstance()
{
if(instance==null) instance = new mySingletonClass();
return instance;
}
//getter setter for userID
}
to set UserID:
mySingletonClass.getInstance().setUserID(String);
to ger UserID:
mySngletonClass.getInstance().getUserID();
Now even if the phone is rooted, the userID is safely residing in heap memory !
If you do want to user SharedPreference for whole app life cycle (install to uninstall) and are worried about phone being rooted and userId being stolen, you can obfuscate the id before storing, but then again you need to store Key in shared preference too which defeats the purpose. Another way can be to store the key on server. Cracker can still snoop in the network calls and access the key but its a long shot.
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.
In one of my App, I would like to give a feature as a trial for only 20 attempts. Once the user wants to access the feature for the 21st attempt, he/she will be prompted for in-App purchase.
My question is how can I make this variable persistent so that even if the user uninstalls the app and re-installs, the counter does not reset and takes the last value before the uninstall.
Please help.
The easiest way is to use Backup API and backup your data online. It is very easy to use and here is tutorial:
http://developer.android.com/training/cloudsync/backupapi.html
The disadvantage of this method is that user can disable backups in phone's settings.
Another method requires you to send data to server. I would suggest to use parse.com since it does not require you to write any server code, they have very easy-to-use library for Android and their free plan is very generous. Here is a little tutorial:
https://parse.com/tutorials/get-started-with-android
You can send some sort of unique id (device or account specific) and counter to the cloud every time user triggers your trial feature. Also you can query your counter from the cloud when application launches the first time.
To create that unique id you can approach with few methods:
Try to obtain 64-bit unique number, which is generated when device first boots:
String androidID = Secure.getString(getContext().getContentResolver(), Secure.ANDROID_ID);
Note that it was reported that for some device this value might be null. You can verify your androidID variable and if it is null, you can try another method that will allow you to access user's primary e-mail (you probably want to hash it prior to sending it your server).
Also make sure to add android.permission.GET_ACCOUNTS permissions to your manifest file:
final Account[] accounts = AccountManager.get(context).getAccounts();
for (final Account account : accounts) {
if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
final String email = account.name;
// hash email and use it
}
}
if email cannot be obtained - you might also want to try to get device id from telephony manager:
// For CDMA phone getDeviceId() is equal to value request for Secure.ANDROID_ID
final TelephonyManager telMgr = (TelephonyManager)getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
final String deviceId = telMgr.getDeviceId();
(don't forget to add android.permission.READ_PHONE_STATE permission to your manifest)
Hope that it gave you enough information to add trial functionality into your code.
Also if your in-app purchase is actually a subscription, then Google already implemented trial functionality for you:
http://developer.android.com/google/play/billing/billing_subscriptions.html
(search for free trial)
You have no way of maintaining anything locally for the user if they uninstall or reinstall the application.
If you need the uninstall/re-install requirement, this is counter that will need to be logged on your back-end rather than on the device. You can do this by storing the device's id on your server and incrementing your ticker when appropriate.
I simply define a serializable Expiration object that I store to SD with a dot in front of it to make it hidden.
The object contains time of creation and other metadata.
When the app starts, it checks whether Expiration exists, if not it is create. This way I always know the exact time when the app was installed, despite uninstall/reinstalls.
The downside to this method is that it requires some sort of external storage as we want to go outside of the standard app folder of the internal storage, which is wiped upon uninstall.
To circumvent this, you could look for some way of getting/giving a device a unique id, that remains the same after reinstall, and upload the data to a server. This has the benefit that the user cannot reset the expiration by wiping the SD either.
I want to allocate unique ID to each user as soon as he installs the application so that whenever the app contacts the server I know who is contacting.
For this purpose, I thought that on first time installation, the app contacts the server and gets unique ID. But I don't know where to store it permanently so that next time when app is started, it knows what its ID is rather than contacting server.
Sorry if that is some obvious question as I am newbie.
This question has been asked many times on Stack Overflow.
In short: Android has always supported a unique ID. However, prior to Android 2.2, the ID was not always identical on certain kinds of phones. Since 2.2 is pretty ubiquitous by now, I would use that ID.
The Android Developer Blog has a good article about this.
And as Joachim said - you may want to consider a different approach altogether. Android's unique ID is good and persistent across factory resets, but not across a device upgrade. Also keep in mind that many people have several devices (like a phone and a tablet). You may want to use the Google account instead, the AccountManager can help you there.
Use SharedPreferences to store the unique id.
Here is an example:
Android SharedPreferences
For more complex data, you can use SQlite.
For unique id, you can use IMEI of device on which application is going to install. Refer this link for how to get IMEI number. Then stored that IMEI number in shared preference. Refer Guillermo lobar's link for that. You need to check for that unique id in preference when you application starts. At very first time, save that in preference. So when next time it checks for that id, app find it in preference and hence no need to connecting server. :)
You could get the IMEI of the device. As of API 26, getDeviceId() is deprecated. If you need to get the IMEI of the device, use the following:
String deviceId = "";
if (Build.VERSION.SDK_INT >= 26) {
deviceId = getSystemService(TelephonyManager.class).getImei();
}else{
deviceId = getSystemService(TelephonyManager.class).getDeviceId();
}
I have created an android application where user need to login to store some info like their score, level and so on which are not needed to make secured or open for all.
Now don't want to prompt user to login or sign up, My question is how my application can automatically grab users identical info like his gmail address for his android account ?
After getting the email i can send the email associating with the application result.
Thanks.
You can store information on SharedPreferences
First register and play...blah blah, done gaming, write result to SharedPreferences
Next time loading, check/read SharedPreferences whether such info/data exists then process ... blah blah
Look up info on SharedPreferences: http://developer.android.com/reference/android/content/SharedPreferences.html
There is a very good example of this in the Google IO videos, unfortunately I cannot remember which one it is.
Basically you create a UUID and store it in the shared preferences so that if it is uninstalled then it respects privacy.
That UUID is then used to key all information, if the user wishes to sign up proplery then this key is used and can later be associated with a google ID making the process completely seamless other than a single sign in.
I think it's in the 2010 videos, but I cannot remember the speaker's name.
There is a link that covers some of the basics here:
How can I get the UUID of my Android phone in an application?