Flutter - Get Unique Device ID - android

I am making an app with token based system. So users can buy tokens and using them they can make some actions.
Each user gets 10 tokens for free (as a trial version) after creating an account using email and password.
I want to prevent that user gets another 10 tokens by getting a new account each time and I was wondering if there is something like unique device ID for both Android and iOS devices?
Can I use this for that purpose? https://pub.dartlang.org/packages/device_id#-example-tab-

Use device_info_plus plugin.
In your pubspec.yaml file add this
dependencies:
device_info_plus: any
Create a method:
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
// ...
Future<String?> _getId() async {
var deviceInfo = DeviceInfoPlugin();
if (Platform.isIOS) { // import 'dart:io'
var iosDeviceInfo = await deviceInfo.iosInfo;
return iosDeviceInfo.identifierForVendor; // Unique ID on iOS
} else {
var androidDeviceInfo = await deviceInfo.androidInfo;
return androidDeviceInfo.androidId; // Unique ID on Android
}
}
Use it like:
String? deviceId = await _getId();
or
_getId().then((id) {
String? deviceId = id;
});

Yes thats the plugin you need. If you really want to
I want to prevent that user gets another 10 tokens by getting a new account each time
You must as well check for rooted phone (it can change id)
You may want to consider using this GET IMEI

Related

Android: How to get device id from a Google Analytics even in firebase - functions

I am trying to get firebase device id in firebase functions (Node JS)
This is the document that I have referenced.
https://firebase.google.com/docs/reference/functions/firebase-functions.analytics.deviceinfo.md#analyticsdeviceinfo_interface
This is how I am trying to get it, but in the logs i can see that its undefined.
const deviceId = functions.analytics.DeviceInfo.deviceId;
Here is my complete code
const admin = require("firebase-admin");
admin.initializeApp();
const database = admin.firestore();
exports.appUninstall = functions.analytics.event("app_remove")
.onLog((event) => {
const deviceId = functions.analytics.DeviceInfo.deviceId;
console.log("deviceId", deviceId);
database.doc("userActivity/uninstalls"+deviceId)
.update({"device_id": deviceId});
return console.log("uninstall event called");
});
How can we get the device id through firebase functions.
I am trying to get the device id when we uninstall the app.
By default we get some information in the event object and it contains the device info as well but it does not contain the device_id. Now I am looking for ways to add the device_id to the event object.

Flutter device_info_plus 'androidId' is not unique. How can I identify an android users device even after reinstalls or updates?

I am using the device_info_plus plugin like this:
Future<void> getHardwareID() async {
final DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
if (Platform.isAndroid) {
final AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
hwid = androidInfo.androidId;
} else if (Platform.isIOS) {
final IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
hwid = iosInfo.identifierForVendor;
}
}
The issue is that when I use the same phone with different versions of the app - so if I upload a new bundle for testing for instance - then androidInfo.androidId will be something different. I suppose this is what they mean with the description
The Android hardware device ID that is unique between the device +
user and app signing.
Eventhough I think with app signing they mean the keystore file and properties which do not change so I am not sure if this is the reason
Apple seems to work fine since iosInfo.identifierForVendor just returns the
Unique UUID value identifying the current device
This is a problem since I would like to keep track of users in a database without them having to register with an account. (How) Is this possible?
There is an id property described like this:
Either a changelist number, or a label like M4-rc20
But that does not sound like what I am looking for
How can I get an ID from an android device that does not change if the app version changes?

How to perform Firebase scheduled function only if value from realtime database is equal X?

I'm starting my adventure with Firebase cloud functions in my adnroid app in Android Studio and I have no experience with it. What is more I have never used javascript before so everything seems to be new for me. I would like to know if I can make a scheduled function that works like this :
At first function checks if value from realtime databse isn't zero.
If not, function checks if another value from realtime database is not bigger than 7.
If not, the value in database is increased by 1.
And then the notification is send.
I made test function to check if data from database are taken corectly but it execute with error "Firebase is not defined".
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
var user = user.uid;
var myRef = firebase.database().ref(user + "/CurrentChallenge/numOfActiveChallenge");
myRef.on('value', (snapshot) => {
const data = snapshot.val();
console.log(data);
});
In a Cloud Function, if you want to interact with the Firebase services, you need to use the Admin SDK.
Also, if you want to read a database node in a Cloud Function, it is more appropriate to read once the node (with get() or once()) instead of setting a listener with on(). As a matter of fact the CF has a short life time and setting a listener is therefore not the correct approach.
It is nor clear how you get the value of the user variable. There is no user in a Scheduled Cloud Function. You need to adapt this line, because, as such it will not work.
Finally, it is important to note that you need to terminate a Cloud Function when all the asynchronous work is completed, see the doc. In the case of a background triggered Cloud Function (e.g. a Pub/Sub schedules Cloud Function) you must return the entire chain of promises returned by the asynchronous method calls. Another possibility is to use async/await, as shown below, and return a value (e.g. null) when all the asynchronous work is completed.
So, the following code skeleton should do the trick:
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun(async (context) => {
var user = ... // Set the value of user
const db = admin.database(); // Admin SDK
const snapshot1 = await db.database().ref("...").get();
if (snapshot1.val() !== 0) {
const snapshot2 = await db.database().ref("...").get();
if (snapshot2.val() <= 7) {
await db.ref("...").update({
fieldName: firebase.database.ServerValue.increment(1)
});
//send the notification
// See https://github.com/firebase/functions-samples/blob/main/fcm-notifications/functions/index.js
} else {
return null;
}
} else {
return null;
}
});
Cloud functions are secure environment just like any server. Generally you use the Firebase Admin SDK when using Firebase in Cloud functions or your own servers. To add firebase admin, open terminal and go to the function directory and run the following command:
npm install firebase-admin
The important thing to note is admin sdk doesn't obey any database security rules as the name says. It has privileged access.
You can try the following code.
const admin = require("firebase-admin")
admin.initializeApp()
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun(async (context) => {
const myRef1Value = (await admin.database().ref("path/to/resoures").once("value")).val()
if (myRef1Value > 0) {
//make another request
}
}
Similarly make multiple requests as needed (sorry for throwing bunch of JS concepts but feel free to ask any queries)
Another thing I noticed is you are trying to get user ID in it. Scheduled Cloud Functions are not invoked by any user so you can't get any UID in that Cloud function. Can you clarify what is your use case so we can figure out a work around for this?
But what you want to achieve is simple chain if else statements and doing stuff.
You'll need to import and initialize the Firebase Admin SDK as shown here:
// The Firebase Admin SDK to access the database
const admin = require('firebase-admin');
admin.initializeApp();
With that, you can then use it with:
var myRef = admin.database().ref(user + "/CurrentChallenge/numOfActiveChallenge");
myRef.once('value', (snapshot) => {
...

How to access iOS UserDefaults stored data in Flutter SharedPrefrences

I have an iOS app already on Store, Now planning to replace it with Flutter with new version release.
I want to get access native app's UserDefaults data in Flutter code.
Using the way suggested in Flutter docs I m getting null value. What I have tried is:
In my pubspec.yaml file :
dependencies:
shared_preferences: ^0.5.12+4
Im my home.dart class file I'm importing header :
import 'package:shared_preferences/shared_preferences.dart';
And this is how I m trying to access data stored in iOS app from native app, I m using same bundle ID (Package ID) in flutter project to overwrite the app and it is successfully overwriting.
#override
void initState() {
super.initState();
getFromLocalMemory('user').then((value) =>
userInfo = value
);
}
Future<String> getFromLocalMemory(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String user = prefs.getString(key);
return user;
}
It always returns null. While 'user' key has data when getting from iOS native app.
We can use existing plugin native_shared_preferences. It allows us to access native SharedPreferences on Android and UserDefaults on iOS.
Sample code to read a value by key "SomeKey":
final someKey = "SomeKey";
var prefs = await NativeSharedPreferences.getInstance();
if (prefs.containsKey(someKey)) {
print("Value for SomeKey: ${prefs.get(someKey)}");
}
In that case, I suggest you use platform channel method
platform channels
iOS doesn't seem to allow flutter framework to access NSUserDefaults, when it didn't create it from the beginning,..
I hope it will work for you.

Expo get unique device id without ejecting

This library allows you to get unique device id / Mac address of Android devices, which doesn't change after reinstallation.
Expo.Constants.deviceId changes after every reinstallation (even if the app version number is the same).
Is there a way to get an unique id for Android that doesn't change after reinstallation (at least for if it's the same version), without ejecting?
For Expo IOS theres currently very limited options, Since Apple forbids getting private device info. We will need to create our own unique identifier below.
Solution:
My solution is a combination of uuid and Expo SecureStore works for IOS and Android.
import * as SecureStore from 'expo-secure-store';
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
let uuid = uuidv4();
await SecureStore.setItemAsync('secure_deviceid', JSON.stringify(uuid));
let fetchUUID = await SecureStore.getItemAsync('secure_deviceid');
console.log(fetchUUID)
This solution will work even if app gets reinstalled, or if user switches devices and copy's all data to new device.
(Expo.Constants.deviceId is deprecated and will be removed in Expo SDK 44).
Full Example:
To check if you already stored the uuid in SecureStore
import * as SecureStore from 'expo-secure-store';
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
let uuid = uuidv4();
let fetchUUID = await SecureStore.getItemAsync('secure_deviceid');
//if user has already signed up prior
if (fetchUUID) {
uuid = fetchUUID
}
await SecureStore.setItemAsync('secure_deviceid', JSON.stringify(uuid));
console.log(uuid)
Use Application.androidId from expo-application. Id will not change after reinstall or update. The value may change if a factory reset is performed on the device or if an APK signing key changes.
https://docs.expo.dev/versions/latest/sdk/application/#applicationandroidid
Example:
import * as Application from 'expo-application';
import { Platform } from 'expo-modules-core';
import * as SecureStore from 'expo-secure-store';
import Constants from 'expo-constants';
const getDeviceId = async () => {
if (Platform.OS === 'android') {
return Application.androidId;
} else {
let deviceId = await SecureStore.getItemAsync('deviceId');
if (!deviceId) {
deviceId = Constants.deviceId; //or generate uuid
await SecureStore.setItemAsync('deviceId', deviceId);
}
return deviceId;
}
}
Guess you can use facebook module for this purpose.
https://docs.expo.io/versions/latest/sdk/facebook-ads/#currentdevicehash
Not sure what happens under hood - but looks like it unique between app reinstal, device restart etc.
Just use getuniqueid() method from react-native-device-info. Works on iOS and android to uniquely identify a device .
To get the device UniqueId in expo project,
npm install react-native-device-info
expo run:ios or expo run:android
Please note: expo start will throw an error

Categories

Resources