I'm making a server that sends messages using FCM to clients depending on what happens (temperature and/or humidity change, a door is opened, etc.).
But if the token can change, how can I keep track of the device to send messages to the correct one (w/o using a login system)?
I was thinking to link the token to the sim iccid in a database, is this correct?
Use device's advertising id. It won't change unless the user manually changes it. Please check the thread How to get Advertising ID in android
Update 05/18/2017:
Starting Android O, ANDROID_ID will now be different per app per user in the device.
Original Answer:
If you're looking for a long lasting (possibly permanent) ID that you can use, I guess you can make use of ANDROID_ID:
String ANDROID_ID
A 64-bit number (as a hex string) that is randomly generated when the user first sets up the device and should remain constant for the lifetime of the user's device. The value may change if a factory reset is performed on the device.
Note: When a device has multiple users (available on certain devices running Android 4.2 or higher), each user appears as a completely separate device, so the ANDROID_ID value is unique to each user.
Constant Value: "android_id"
However, there are still some factors that you should consider depending on your use-case. I recommend going through the Best Practices for Unique Identifiers documentation.
FCM wise, it is usually associated with a user, hence it is commonly paired with the user details.
Related
Im trying to develop an app which has a few security options, and for one of those options I need to able to know if the device is locked with any kind password(numbers,pattern,etc) so I started reading the android documentation and found two KeyguardManager methods, isDeivceLocked() and isDeviceSecured() however I don't really see much of a difference in the description, so what really is the difference between the two? thanks in advance
The official API states the difference, though it might be a bit confusing. The key difference is whether you want to know the general configuration of the device, or its current state.
So isDeviceLocked() returns true if the device is currently locked behind some kind of password or identification mechanism, which is required in order to unlock and use the device. It returns false in case that the device is currently open and in use, or that it just doesn't require any password/identification in order to open it. (reference and more details may be found here)
On the other hand, isDeviceSecure() returns true if the device has been configured to use any kind of password or identification mechanism - even if it's not currently required in order to use the device.
In case you wonder what scenario might cause isDeviceSecure to return true, while isDeviceLocked returns false: it might happen whenever the device in in use (after the lock password has already been entered). Another scenario might be when the device has Smart Unlock (or trusted devices) configured, so that currently it wouldn't ask for a password or any other kind of identification in order to open/unlock itself.
I thought there would be some straight forward solution to this.
Requirements:
Uniquely identify device across app install/uninstall sessions.
Options:
Use some kind of Android's device-identifier-API each time when needed (read it every time from Android's API). According to Identififying-app-installations blog post this is not recommended and not reliable solution.
Generate UUID once (on first app start) and persist it somewhere somehow that it would be preserved across multiple app installs/uninstalls. This "somewhere somehow" part is the mystery. Solutions like storing onto the SD card or Cloud are not an option. iOS has keychain that can be used for this kind of stuff but I didn't find Android's equivalent of it.
What are my other options here? I prefer going the (2) route because of my server implementation (server is generating UUID for the first time if not present). But if it is not an option, I can fallback to (1) and modify the server.
Thanks.
To uniquely identify an application between application installs/reinstalls, you need to get it's hardware ID and use that as your credentials/key.
To fetch the hardwareID, you can use the following method:
public static String getHardwareId(Context context) {
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
it's partially equivallent to a UUID with the following exception: The value may change if a factory reset is performed on the device.
The reason why i call it "partially equivallent" is this:
The HardwareID is a 64-bit number (as a hex string) that is randomly generated when the user first sets up the device and should remain constant for the lifetime of the user's device. The value may change if a factory reset is performed on the device.
Note: When a device has multiple users (available on certain devices running Android 4.2 or higher), each user appears as a completely separate device, so the ANDROID_ID value is unique to each user.
But this hits the #2 problem: where and how to store it; storing it in SharedPreferences is useless as that is wiped if the app is uninstalled. Same for /data/data/your.package.name/my_stored_keys folder as that one gets deleted from the phone during uninstallation as well.
You will need to save it server-side if you wish to persist between uninstalling and reinstalling the app.
In Android Open Source Project, a lot of core API declarations have an integer parameter userId in the end. I traced back and figured out the integer comes from a class called "UserHandle.java". There is a simple comments saying this class represents a user on the device. It still confuses me. Why do we need such a class? What's the difference between different values of the class, such as "USER_OWNER", "USER_CURRENT", "USER_CURRENT_OR_SELF"?
Thanks in advance!!!
Ever since Jelly Bean, Android platform has supported multiple users. This means that multiple users may be able to use one device, yet not be able to access other user's files or communicate with another user's app.
The first user on the device is user 0. The rest start their numbering from 10,11,... (In JB the numbering was 1,2...).
USER_OWNER is user 0.
He has some extra privileges over the other users (mostly access certain settings that others can't or uninstall an app for all users).
Multiple users on one device requires that only one user can be active in a specific point in time, this user is referred to as USER_CURRENT (since Kitkat().
In general one user's application can't send a broadcast message or an Intent to other user's apps.
Only apps with system permissions can do that (for example when the battery is running low, an intent will be sent to all).
Whenever you send an Intent from your app, the system service verifies whether this is a valid Intent i.e. if its supposed to reach all users then it's not.
This means that even if you were to use a certain api with the wrong userId (for example you force userId=0 even though this is user 10), then your call will receive a SecurityException.
To avoid such exceptions, there is also the option to send an Intent with USER_CURRENT_OR_SELF.
This means you're trying to send to the current user, but if he's not allowed to receive the Intent, let the same user who sent the Intent receive it.
I am going to enter the Samsung 2013 app contest, and one of the requirements is that you use their Chord API http://developer.samsung.com/chord.
I plan on allowing users to send messages to all phones that have my app installed. From what I gathered from the information in the previous link, this means that I will need to have a constantly running background process for users to receive the messages when they are not looking at the app at the time.
I want to know if this is true, and if so, is this viable? I am considering using the method detailed here: Android: keeping a background service alive (preventing process death) if I go ahead with this.
I'm trying to use Samsung Chord too. I thing you don't need to do this. Samsung's API Chord already provides this control.
According Chord's API:
"If a Chord node doesn’t receive a UDP signal within a specified amount of time, it considers the “missing”
node to no longer be part of the network."
And, the only thing you have to do is:
"A node cannot receive a UDP broadcast if it is in LCD-off status. Therefore, if developers want the node to discover other nodes while the application is running, the node’s status should be set to LCD-on. To do this, use Android’s PowerManager.WakeLock."
Best regards,
Adriano
This is a theoretical situation:
I am writing an app to detect the presence of another on the phone
The classpath, name, Activity names etc. of the target app have been randomized, I can't just check if it's there (it is semantically the same but syntactically unique)
I have root access to the phone
The app is open source, and (apart from the package name and application name) I know everything about it.
The app generates no Log output.
I've been thinking of ways to detect whether this other app is present on the phone (assuming it is actually run from time to time), are the following methods feasible at all?
Look periodically for the presence of certain classes in memory
Search for known chunks of the compiled code in each installed apk
Detect the app running by inspecting the memory of the device at certain intervals and look for usage patterns matching the app
Are there any other ways of detecting another app under these circumstances?
Use PackageManager. It has a method returning info about all the apps, installed on the system: getInstalledPackages().