Issue
I am working in a Flutter app with some security requirements, one of them is to prevent the app from working in Emulators, just real devices, in order to prevent the screenshots and screen recordings from the Emulators.
I have used safe_device and device_info_plus packages to detect whether the app is running on Emulator or Physical device and every thing is working fine but when I tried LD Player
Emulator the packages failed to detect that it is emulator because it is very good at mocking the real device.
So any ideas to detect that the device is running on LD Player
?
Here is the output from device_info_plus
which might be helpful:
{
"id": "N2G48B",
"host": "ubuntu",
"tags": "release-keys",
"type": "user",
"model": "ASUS_Z01QD",
"board": "SM-G975N",
"brand": "asus",
"device": "aosp",
"product": "SM-G975N",
"display": "N2G48B",
"hardware": "android_x86",
"androidId": null,
"bootloader": "unknown",
"version": {
"baseOS": "",
"sdkInt": 25,
"release": "7.1.2",
"codename": "REL",
"incremental": "V9.5.8.0.OCACNFA",
"previewSdkInt": 0,
"securityPatch": "2017-10-05"
},
"fingerprint": "google/android_x86/x86:7.1.2/N2G48B/V9.5.8.0.OCACNFA:user/release-keys",
"manufacturer": "asus",
"supportedAbis": [
"x86",
"armeabi-v7a",
"armeabi"
],
"systemFeatures": [
"android.hardware.sensor.proximity",
"android.hardware.sensor.accelerometer",
"android.software.controls",
"android.hardware.faketouch",
"android.hardware.usb.accessory",
"android.software.backup",
"android.hardware.touchscreen",
"android.hardware.touchscreen.multitouch",
"android.software.print",
"android.hardware.ethernet",
"android.software.activities_on_secondary_displays",
"android.hardware.wifi.rtt",
"com.google.android.feature.PIXEL_2017_EXPERIENCE",
"android.software.voice_recognizers",
"com.google.lens.feature.CAMERA_INTEGRATION",
"android.software.picture_in_picture",
"android.hardware.fingerprint",
"android.hardware.sensor.gyroscope",
"android.hardware.audio.low_latency",
"android.software.vulkan.deqp.level",
"com.google.android.feature.PIXEL_2018_EXPERIENCE",
"android.hardware.opengles.aep",
"android.hardware.bluetooth",
"android.hardware.camera.autofocus",
"com.google.android.feature.GOOGLE_BUILD",
"android.hardware.telephony.gsm",
"android.hardware.telephony.ims",
"android.software.sip.voip",
"android.hardware.vr.high_performance",
"android.hardware.usb.host",
"android.hardware.audio.output",
"android.software.verified_boot",
"android.hardware.camera.flash",
"android.hardware.camera.front",
"android.hardware.sensor.hifi_sensors",
"android.hardware.se.omapi.uicc",
"android.hardware.screen.portrait",
"android.hardware.nfc",
"com.google.android.feature.TURBO_PRELOAD",
"android.hardware.sensor.ambient_temperature",
"com.nxp.mifare",
"android.hardware.sensor.stepdetector",
"android.software.home_screen",
"android.hardware.microphone",
"android.software.autofill",
"android.software.securely_removes_users",
"android.software.vr.mode",
"com.google.android.feature.PIXEL_EXPERIENCE",
"android.hardware.bluetooth_le",
"android.hardware.sensor.compass",
"android.hardware.touchscreen.multitouch.jazzhand",
"android.hardware.sensor.barometer",
"android.software.app_widgets",
"android.software.input_methods",
"android.hardware.sensor.light",
"android.hardware.vulkan.version",
"android.software.companion_device_setup",
"android.software.device_admin",
"com.google.android.feature.WELLBEING",
"android.hardware.wifi.passpoint",
"android.hardware.camera",
"com.google.android.feature.ZERO_TOUCH",
"android.hardware.screen.landscape",
"android.software.device_id_attestation",
"android.hardware.ram.normal",
"android.software.managed_users",
"android.software.webview",
"android.hardware.sensor.stepcounter",
"android.hardware.camera.capability.manual_post_processing",
"com.google.ar.core.depth",
"android.hardware.camera.any",
"android.hardware.camera.capability.raw",
"android.software.connectionservice",
"android.hardware.touchscreen.multitouch.distinct",
"android.hardware.location.network",
"android.software.cts",
"android.software.sip",
"android.hardware.camera.capability.manual_sensor",
"android.software.app_enumeration",
"com.google.android.apps.dialer.SUPPORTED",
"android.hardware.camera.level.full",
"android.hardware.wifi.direct",
"android.software.live_wallpaper",
"com.google.android.feature.GOOGLE_EXPERIENCE",
"android.software.ipsec_tunnels",
"com.google.android.feature.EXCHANGE_6_2",
"android.software.freeform_window_management",
"android.hardware.audio.pro",
"android.hardware.nfc.hcef",
"android.hardware.location.gps",
"android.software.midi",
"android.hardware.nfc.any",
"android.hardware.nfc.hce",
"android.hardware.wifi",
"android.hardware.location",
"android.hardware.vulkan.level",
"android.hardware.wifi.aware",
"android.software.secure_lock_screen",
"android.hardware.telephony",
"android.software.file_based_encryption",
null
],
"isPhysicalDevice": true,
"supported32BitAbis": [
"x86",
"armeabi-v7a",
"armeabi"
],
"supported64BitAbis": []
}
Solution
The solution is to check for the existence of these folders, if any of them exists, then it is an LD Player
.
'/storage/emulated/0/storage/secure',
'/storage/emulated/0/Android/data/com.android.ld.appstore'
I have implemented a method to take a list of folders paths and return true if any of them exists, which is the following:
bool anyFolderExists(List<String> foldersPaths) {
for (String folderPath in foldersPaths) {
if (Directory(folderPath).existsSync()) {
return true;
}
}
return false;
}
and I'm using it like this:
List<String> harmfulFoldersPaths = [
'/storage/emulated/0/storage/secure',
'/storage/emulated/0/Android/data/com.android.ld.appstore',
];
if(anyFolderExists(harmfulFoldersPaths))
{
print('LD Player Detected!');
}
Also I am using these two values from the output of device_info_plus package to decide that the app is working on an Emulator because they seems very generic:
"host": "ubuntu",
"device": "aosp",
I am using them like the following:
final androidInfo = await deviceInfoPlugin.androidInfo;
if (androidInfo.host == 'ubuntu' && androidInfo.device == 'aosp') {
print('LD Player Detected!');
}
But to be honest, I am afraid of this approach because I do not want to block any user by mistake, so I am using them with Firebase Remote Config to enable/disable it at any time but until now I am enabling them without any problem recorded.
Answered By - Moaz El-sawaf
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.