Flutter: How to detect that the app is running on LD Player - android

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": []
}

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.

Check this Package
https://pub.dev/packages/safe_device
bool isRealDevice = await SafeDevice.isRealDevice;
this method returns false if running device is an emulator

Related

Appium Ruby - Can't Scroll To Accessibility_ID

http://appium.io/docs/en/commands/interactions/touch/scroll/
I want to scroll to an element. I keep getting an error. Fix may be simple but I'm totally lost.
Error: "undefined method `scroll' for #<Appium::TouchAction:0x000055d15d31c980> (NoMethodError)"
I am on:
Linux Mint
Ruby version 2.5.1p57
touch_action gem (1.3.3)
appium_lib gem (10.6.0)
appium_lib_core gem (3.7.0)
Below is my code.
require 'appium_lib'
require 'touch_action'
#require 'selenium-webdriver'
server_url = "http://127.0.0.1:4723/wd/hub"
opts = {
caps: {
platformName: :Android,
platformVersion: 9,
deviceName: :'Android Emulator',
app: 'TheApp-v1.9.0.apk',
newCommandTimeout: 600,
automationName: :Appium,
javascript_enabled: true
}
}
driver = Appium::Driver.new(opts, true)
driver.start_driver
ta = Appium::TouchAction.new.driver
sleep 5
scroll1 = ta.scroll_to(:accessibility_id, "Verify Phone Number")
scroll1.perform
sleep 2
print "Completed Successfully!"
driver.driver_quit
scroll_to has historically been flaky in Ruby Appium. I'd suggest writing your own logic similar to the following:
ta = Appium::TouchAction.new.driver
swipeUp = ta.swipe(startX, startY, endX, endY, duration)
clicked = false
(0...times).each do
swipeUp.perform
unless verifyPhoneNumber.isDisplayed
verifyPhoneNumber.click
clicked = true
end
break if clicked == true
end
My Ruby and Appium are a bit rusty; apologies if there are any errors above, but you should get the gist.
For reusability, I'd probably create a function with this logic that returns the element you were attempting to scroll to.
Following Worked for me (solution is for Ruby+Appium+Android)
require 'rubygems'
require 'appium_lib'
desired_caps = {
"appium:deviceName": "055542505S003131",
"platformName": "android",
"appium:appPackage": "app.endometriose.android",
"appium:noReset": true,
"automationName": "UiAutomator2",
"appium:appActivity": "host.exp.exponent.MainActivity",
"app": "/users/user/myApp.apk"
}
appium_driver = Appium::Driver.new({'caps' => desired_caps, }, true)
# Scroll
appium_driver.scroll_to("Button")
**Note:** scroll_to methods takes visible text of the element and scroll to it.

Adaptive card is not rendered on Teams mobile app

We have an external bot configured to use MS Teams channel using message end point web hook. The following is the message posted to the Ms Teams channel by the external bot. This response gets rendered as expected when MS Teams is accessed via web browser or MS Teams application on desktop computer. However, the card is not rendered (seeing an empty line/block without any content) when used with Teams application on an android mobile phone. Would like to know what is going wrong here?Is this feature not supported on mobile? or are we missing something?
"channelData":{
"tenant":{
"id":"xxxxxxxxxxxxxx"
}
},
"attachments":[
{
"contentType":"application/vnd.microsoft.card.adaptive",
"content":{
"fallbackText":"Adaptive card version not supported",
"type":"AdaptiveCards",
"body":[
{
"text":"Here is an adaptive card with a link to a task module",
"type":"TextBlock"
},
{
"type":"Image",
"url":"http://adaptivecards.io/content/cats/1.png"
}
],
"version":"1.0",
"actions":[
{
"type":"Action.OpenUrl",
"title":"Open Link",
"url":"https://teams.microsoft.com/l/task/xxxxx?url=https%3A%2F%2Fwww.wikipedia.com%0A&height=large&width=large&title=Wikipedia-Embed"
}
]
}
}
],
"replyToId":"xxxxxx",
"serviceUrl":"https://smba.trafficmanager.net/amer/",
"recipient":{
"name":"xxxx xxxx",
"aadObjectId":"xxxxx",
"id":"xx:xxxxxxxx"
},
"localTimestamp":"2020-02-14T15:21:41.1360000-08:00",
"channelType":"msteams",
"from":{
"name":"xxxxxx",
"id":"xx:xxxxx"
},
"type":"message",
"conversation":{
"conversationType":"personal",
"tenantId":"xxxxxx",
"id":"x:xxxxxx"
}
}```
You need to make sure the card's "type" is "AdaptiveCard" and not "AdaptiveCards".
{
"fallbackText":"Adaptive card version not supported",
"type":"AdaptiveCard",
"body":[
{
"text":"Here is an adaptive card with a link to a task module",
"type":"TextBlock"
},
{
"type":"Image",
"url":"http://adaptivecards.io/content/cats/1.png"
}
],
"version":"1.0",
"actions":[
{
"type":"Action.OpenUrl",
"title":"Open Link",
"url":"https://teams.microsoft.com/l/task/xxxxx?url=https%3A%2F%2Fwww.wikipedia.com%0A&height=large&width=large&title=Wikipedia-Embed"
}
]
}

Getting and playing 30 second previews from Spotify

I've looked into how to play 30 second previews but so far all I can find is android wrappers for the web API that require user authentication.
I need to be able to search for an artist and play the first preview that pops up without needing the user to authenticate their accounts
You should check: https://developer.spotify.com/web-api/code-examples/
"Search for an Artist (and Lookup) Demo"
It's an example for a web snippet, but you could try to see how it does the connection without needing the user authentication.
If you look at spotify api webpage they mention Endpoints marked “OAuth” above require application registration and user authorization via the Spotify Accounts Service to access certain data.
So in order to get this working i had to chain 2 API calls together. The first one searches for the artist and then the second one looks for the preview:
You call the API with this link (GET):
https://api.spotify.com/v1/search?q=<artist name>&type=artist
which then returns a json structure like this:
{
"artists": {
"href": "https://api.spotify.com/v1/search?query=bring+me+the+horizon&offset=0&limit=20&type=artist",
"items": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/1Ffb6ejR6Fe5IamqA5oRUF"
},
"followers": {
"href": null,
"total": 1067846
},
"genres": [
"metalcore"
],
"href": "https://api.spotify.com/v1/artists/1Ffb6ejR6Fe5IamqA5oRUF",
"id": "1Ffb6ejR6Fe5IamqA5oRUF",
"images": [
{
"height": 640,
"url": "https://i.scdn.co/image/49aad7da4f872acb3005727392631dab282423d1",
"width": 640
},
{
"height": 320,
"url": "https://i.scdn.co/image/d9cf89b9db73b95ed15d9e29e30d0dd8afea23e2",
"width": 320
},
{
"height": 160,
"url": "https://i.scdn.co/image/d9e514e15f4940c77029ef3b11291d557b345ae9",
"width": 160
}
],
"name": "Bring Me The Horizon",
"popularity": 76,
"type": "artist",
"uri": "spotify:artist:1Ffb6ejR6Fe5IamqA5oRUF"
}
],
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total": 1
}
}
Because this then returns the Artist ID we can get the top tracks for that artist and play a preview:
Call the API with this URL (GET):
https://api.spotify.com/v1/artists/<ARTIST ID>/top-tracks?country=GB
From here we can then extract the URL of the preview and play it, all without authentication!

error page occurs while accessing buy link of Google books API result

i am doing a bar code scanner application.I am trying to get Google book details from the bar code ISBN number in android application. Also i got all the book details from API result successfully. But if i try to access the buy link from API result, i am unable to access the buy link of the book. It says 404 error. Can anyone help me, how to access the buy link to buy a book.? Thanks in advance.
Here is the buy link of book got from below result:
http://books.google.co.in/books?id=xqxBtXmxqV4C&dq=isbn:9781849699327&hl=&buy=&source=gbs_api
Here is the API result:
"saleInfo": {
"country": "IN",
"saleability": "FOR_SALE",
"isEbook": true,
"listPrice": {
"amount": 162.0,
"currencyCode": "INR"
},
"retailPrice": {
"amount": 113.4,
"currencyCode": "INR"
},
"buyLink": "http://books.google.co.in/books?id=xqxBtXmxqV4C&dq=isbn:9781849699327&hl=&buy=&source=gbs_api",
"offers": [
{
"finskyOfferType": 1,
"listPrice": {
"amountInMicros": 1.62E8,
"currencyCode": "INR"
},
"retailPrice": {
"amountInMicros": 1.134E8,
"currencyCode": "INR"
}
}
]

Facebook social plugin on android

I would like to integrate Facebook's comment social plugin
( https://developers.facebook.com/docs/reference/plugins/comments/ to comment on url) into my android application.
I tried to use webview (use this answer Android unable to implement facebook comment in a webview due to default browser ) and it's work, but hard to customize, for example: I want to have a bigger Textbox for user to type the comment. My question is: "is there any solution to integrate something like "Facebook's comment social plugin" into android application by facebook sdk, java code,... to comment on url?
Thanks & best regards
As far as I understand you have some URL page where you've embedded your facebook social plugin with comments and you want to parse this and display as you want. If I'm right, then unfortunately I haven't found easy solution via triggering appropriated methods from Facebook SDK. You have to use Graph API.
First of all we need to take a look into docs - https://developers.facebook.com/docs/graph-api/reference/v2.3/object/comments
Here there is a example of call
/* make the API call */
new Request(
session,
"/{object-id}/comments",
null,
HttpMethod.GET,
new Request.Callback() {
public void onCompleted(Response response) {
/* handle the result */
}
}
).executeAsync();
For getting {object_id} you need to send similar call to the Graph API, but for retrieving id:
GET-> ?id=http%3A%2F%2Fwww.imdb.com%2Ftitle%2Ftt2015381%2F
And you will receive response which looks like
{
"og_object": {
"id": "10150298925420108",
"description": "Directed by James Gunn. With Chris Pratt, Vin Diesel, Bradley Cooper, Zoe Saldana. A group of intergalactic criminals are forced to work together to stop a fanatical warrior from taking control of the universe.",
"title": "Guardians of the Galaxy (2014)",
"type": "video.movie",
"updated_time": "2015-05-15T14:52:46+0000",
"url": "http://www.imdb.com/title/tt2015381/"
},
"share": {
"comment_count": 4,
"share_count": 91073
},
"id": "http://www.imdb.com/title/tt2015381/"
}
10150298925420108 is our object_id
So next query looks like GET -> 10150298925420108/comments
and response
{
"data": [
{
"id": "10150298925420108_10152457293990108",
"can_remove": false,
"created_time": "2014-10-28T18:12:15+0000",
"from": {
"id": "1513986108857171",
"name": "ซอโซ่ สระอา ยอยัก"
},
"like_count": 2,
"message": "สนุกมากค่ะ",
"user_likes": false
},
{
"id": "10150298925420108_10152457392770108",
"can_remove": false,
"created_time": "2014-10-28T19:20:28+0000",
"from": {
"id": "302917246580502",
"name": "สมชาย โกทันธ์"
},
"like_count": 0,
"message": "สองดาวครับ\n",
"user_likes": false
},
{
"id": "10150298925420108_10152461977130108",
"can_remove": false,
"created_time": "2014-10-31T11:57:10+0000",
"from": {
"id": "472810482857795",
"name": "Surat Thaenphet"
},
"like_count": 0,
"message": "แต่ละเรื่องที่ลง สนุกมาก แต่ดูไม่จบ ดูสักพัก ก็ eror ไม่รุ้เป็นเพราะอะไร",
"user_likes": false
}
],
"paging": {
"cursors": {
"before": "Mw==",
"after": "MQ=="
}
}
}
To test all this requests and response before doing it in Android app - use Graph API explorer https://developers.facebook.com/tools/explorer/

Categories

Resources