How to do user identification in Android? - android

I recently started learning Android to port my iOS app to Android.
User registration in my app is optional, hence the user can decide to get started right away without any delay. However I still need a form of identification against fraud and if the user has passed the first week of free trial. Otherwise the user can just keep deleting and reinstalling the app to use it for free, forever.
On iOS I have solved the problem through the keychain. Any values stored in there remain there even after the app has been uninstalled.
import KeychainAccess
let keychain = Keychain(service: Constants.keychainServiceID).synchronizable(false).accessibility(.alwaysThisDeviceOnly).accessibility(.alwaysThisDeviceOnly)
let deviceId = UUID().uuidString.lowercased()
keychain["DEVICE_ID"] = deviceId
I don't seem to find anything like that on Android.
A unique Device ID doesn't seem to be available either based on this answer
Hence is there a way to achieve this or do I have to make user registration mandatory?
UPDATE:
In iOS when a keyChain value is set, the user can't ever update or delete it. Even after the app is uninstalled. During unit testing I can delete the keychain entry like this:
let keychain = Keychain(service: Constants.keychainServiceID).synchronizable(false).accessibility(.alwaysThisDeviceOnly)
do {
try keychain.remove("DEVICE_ID")
} catch let error {
print("error: \(error)")
}
Can I do that in Android?

More easily you can do like this, this is a wrapper on shared preference.
https://github.com/kishandonga/EasyPrefs
public static void setUniqueId(){
if(!Prefs.read().content("is_unique_id_set", false)){
String id = UUID.randomUUID().toString();
Prefs.write().content("unique_id", id)
.content("is_unique_id_set", true)
.commit();
}
}
public static String getUniqueId(){
return Prefs.read().content("unique_id", "");
}
Cases when unique id changed
App uninstalled and then reinstalled
Clear cache or reset

Related

Firebase Auth saved after uninstall. How can I delete it?

I've recently discovered that Firebase Auth saves itself on the device even after my app is uninstalled. I can't figure out how to REMOVE this old Auth info.
I don't want a user to still be signed in after uninstalling and reinstalling the app. If for no other reason than my own testing of what I expect to be "clean installs" on the same device.
I understand there is no easy way to capture an uninstall event, so I want to clear out any potential old Auth info on the first launch.
So I added code (which seems to work fine) to check if this is the first launch:
Boolean firstRun = prefs.getBoolean("firstrun", true);
if (firstRun) {
// delete everything an old user could have left behind
// ==> This is where I need help <==
prefs.edit().putBoolean("firstrun", false).apply();
} else {
// move along, not the first launch
}
I've tried (unsuccessfully):
FirebaseAuth authData = FirebaseAuth.getInstance();
authData.signOut();
These calls also seem to be the advice in this related question for iOS, but I haven't been able to apply its wisdom:
Firebase - Deleting and reinstalling app does not un-authenticate a user
Even after calling signOut() the app keeps logging me in under the old account!
My "logout" button uses FirebaseAuth.getInstance().signOut(); and works. Is there something odd (possessed?) about this "old" Auth instance that is being saved after an uninstall that it just won't die?
Specifically when I uninstall and then install/run from Android Studio:
at first authData and currentUser both are not null
I call the above code, trying to get rid of this old user
3 millisecond later (immediately after I call that
code) they are still NOT NULL.
Another 2 milliseconds, currentUser IS NULL (yay?)
Another 71 milliseconds... still null (so far so good)
Just under a second later... I'M SIGNED IN AS THE OLD USER?! How is this possible?
In the Firebase Console under Authentication, this account is shown as last signed in 6 days ago. So it's not somehow getting re-signed-in.
Does anyone know how to remove FirebaseAuth data from a device? I don't want to "delete" the user account, just remove all traces of it from this device.
Oddly enough, the account I keep getting unwillfully logged in under isn't even the last account that logged into my app on this device. And this was never a problem in the past (hence my not even knowing that Firebase saved Auth after uninstall). So it looks like Auth info isn't always saved after uninstall... but when it happens it's impossible to remove?
Any help much appreciated!
Add android:allowBackup="false" in your <application> in manifest:
From the docs:
android:allowBackup
Whether to allow the application to participate in the backup and restore infrastructure. If this attribute is set to false, no backup or restore of the application will ever be performed, even by a full-system backup that would otherwise cause all application data to be saved via adb. The default value of this attribute is true.
Try also FirebaseAuth.getInstance().getCurrentUser().delete
Firebase stores auth info in shared preference with file names starting with "com.google.firebase.auth.api.". Therefor if you delete these files as part of your log off flow it would help the purpose.
public void clearFirebaseAuthInfo(Context ctx)
{
File dir = new File(ctx.getFilesDir().getParent() + "/shared_prefs/");
String[] children = dir.list();
for (int i = 0; i < children.length; i++)
{
if(children[i].contains("com.google.firebase.auth.api."))
{
new File(dir, children[i]).delete();
}
}
}

Anonymous account that sticks through app uninstall/reinstall

I’ve seen apps where users can create a guest account (anonymous) without password, and when they delete the game and reinstall it, they’re still logged in to their guest account.
I’ve also seen some apps where this situation would create a new guest account every time. I’d like to avoid this in my app but I don’t know how to.
Anyone knows how this is done?
Thanks,
Tom
So you want to generate userId and persist it through app reinstalls. In android I heard that there is no problem to get unique identifier. In iOS you can use framework like JNKeychain. Then you generate unique value. In obj-c you may wish to use such code.
NSString* deviceId = [JNKeychain loadValueForKey: #"deviceId"];
if (!deviceId)
{
if (![JNKeychain saveValue: [[NSUUID UUID] UUIDString] forKey: #"deviceId"])
{
deviceId = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
else
{
deviceId = [JNKeychain loadValueForKey: #"deviceId"];
}
}

Android - Windows Live API, User has to sign in every time?

I am trying to submit a status from my application to Window's live, the user starts the app, gets asked to give my app permissions to do this, and once granted I have a live session object and I can update their status. This works perfectly.
However, if the user closes the application and then opens it again, they are again asked to approve my app for this action. Every time.
Now the live documentation says you can obtain a refresh token (which I do) to prevent this, problem is the access token and the refresh token are all baked in the LiveConnectSession, so when my application is closed this object is destroyed and the user is asked to give the app permissions again.
So what I'd like to know is if anyone knows a way of recreating that object when the application starts (if I stored the token and refresh token) or a way of saving the object onDestroy()..
Iterable<String> scopes = Arrays.asList("wl.signin", "wl.share", "wl.offline_access" );
this.auth.login(this, scopes, this);
public void onAuthComplete(LiveStatus status, LiveConnectSession session, Object userState) {
if(status == LiveStatus.CONNECTED) {
Log.d("", "Signed in.");
client = new LiveConnectClient(session);
stuck with the same issue using Windows Phone..
I have tried serializing the session, which does not work because the session class has no default constructor.
EDIT:
after two full days searching for the mistake I was making, I finally found out what I was doing wrong: I have to use the wl.offline_access scope to make this work!
Now everything is fun again. Can't believe that this was the problem. Tested & working. Nice!
As I can see, you are using the offline scope, so that's not the problem for you.
But I have found out more:
there are two ways to connect to Live (in C#, I don't know how the methods are called in Java):
use LiveConnectClient.LoginAsync (which comes with GUI)
use LiveConnectClient.InitializeAsync (which is UI less and connects in background)
So if your application is already connected, use the second one to gain access to a new session object.
AFAIK, this object is valid for one year, after that, the user has to sign in again. But don't quote me on that.
Please let me know if this works for you.

Android set a limit of installations allowed per .apk

Is there a standard way to limit the number of installations allowed by an .apk
If I understand correctly Timestamp limits the time an .apk is valid for installation, is there something similar to this that limits the installation count.
I'm planning on using DeviceID and UserID to populate a DB that checks logs for used User ID / Device ID combination to allow or not allow access, once the app is installed.
Thing is I'm trying to prevent the app from even being installed if its over x number of installations.
I was thinking about something like:
package com.tchip.kw;
public class mysoft {
static {
try{
System.loadLibrary("tchipmysoft");
}
catch(Exception e)
{}
}
public native int getmachinestatus1();
public native int getmachinestatus2();
}
 
///this will read/call 2 solutions from mysoft when the end users try to run app. If the return value is 0, then it will say’ Quit’. For example:
 
mysoft kw = new mysoft();
    #Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //this.findViewById(id)
        if (kw.getmachinestatus1() && kw.getmachinestatus2() )
        setContentView(R.layout.main);
/////Star splash activity
else
{
You do not have proper license to use this software and it will quit
}
}
I've thought about writing an installation .APK for the for the app.apk that checks for a set of Key's held remotely and then grants access.
If there is a standardized method or am I missing something really simple, I'm all ears.

what is the most accurate way to know if the visitor to a mobile webapp is unique?

I need to develop a webapp that needs to know the unique identifier (mac address, for example) of the smartphone that is using it. Most of the methods I'm looking at are cookie/IP based but this is not useful in my case scenario as I'm trying to match the use of a native Android app to the use of its counterpart webapp.
So, is this even possible? If it is, which technology should I use for the webapp development?
Thanks!
You could leave a UUID cookie with the user. When they hop on the app, check the UUID against your list of previous visitors. If you find it, they are not unique.
Edit: by cookie, I mean you could just leave a UUID string file on the user's sd card or store it in a preference of the app.
Presumably the application is installed from the Android Market, so you can't match a site cookie passed in the download URL (or, doubtless, that's exactly what you'd do).
That being the case, can you use URL rewriting? Or at least insert a unique ID into each access to your website, doubtless corresponding to a cookie. Then, when the user downloads the application and runs it the first time it can access the Browser history and look for this unique ID, store it (if it exists) and include it with subsequent server requests.
int occasions=0;
String sessionId = null;
while (cursor.moveToNext()) {
String urlVisited=cursor.getString(cursor.getColumnIndex(BookmarkColumns.URL));
Log.d("Match",urlVisited);
if (urlVisited.contains("www.mysite.com") && urlVisited.contains("MYUNIQUEID")) {
//There's a unique ID. Trim it out of the query string.
sessionId=urlVisited.substring(urlVisited.indexOf("MYUNIQUEID")+10);
if (sessionId.indexOf('&')>-1) {
sessionId=sessionId.substring(0,sessionId.indexOf('&'));
}
occasions++;
}
}
Log.d("Match","occasions="+occasions);
if (sessionId!=null) {
getSharedPreferences("com.mysite", MODE_PRIVATE).edit().putString("SITEID", sessionId);
}
This seems like a bit of a hack - possibly because it is - but it should work and I can't think of another sure way to link browser and custom client requests. Of course if the user cleans his history or cookies before downloading and running the application then the above will not work.
I hope that's of some help.

Categories

Resources