Geocoder returns false on isPresent() - java

So I wrote some code for maps in my app, and it works on my phone just fine, sadly it does not work on my emulator which is not comfortable enough for me here is the code:
String searchString = mSearchText.getText().toString();
Geocoder geocoder = new Geocoder(this);
List<Address> list = new ArrayList<>();
try{
int i=0;
while(list.size()==0 && i<10) {
boolean a = geocoder.isPresent();
list = geocoder.getFromLocationName(searchString,1);
i++;
}
}catch(IOException e){
Log.d(TAG, "geoLocate: IOException " + e.getMessage());
}
So when I debug it I see that variable "a" is always false on my emulator.
I use android emulator for visual studio since I have an AMD processor (Ryzen 7 1800x) on which I installed google play store and google play services(map works just fine, just geocoder doesn't), now is there some way to fix it?
As I read on https://developer.android.com/reference/android/location/Geocoder.html
website "The Geocoder query methods will return an empty list if there no backend service in the platform." Can I get the service somehow? Download it on my emulator or something like this?

First, isPresent() is a static method so the call should be
Geocoder.isPresent();
IsPresent method "Returns true if the Geocoder methods getFromLocation and getFromLocationName are implemented" and false otherwise. Some emulators don't have the geocoder service installed. Is the method
geocoder.getFromLocationName
returning what you need or an empty array?
Your snippet works just fine on my Nexus 6P Android 7.0 API 24 emulator.

Related

Text to Speech Android Studio

I am trying to do a TTS app for Arabic however whenever I want to initialize my TTS it always fails. I have no idea what I'm supposed to do to fix it. I tried to enter the TTS engine on the emulator but it doesn't show me anything. So I'm unsure whether the issue is from the emulator or my code.
TTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status==TextToSpeech.SUCCESS){
int res = TTS.setLanguage(Locale.forLanguageTag("ar-XA"));
if (res == TextToSpeech.LANG_MISSING_DATA || res == TextToSpeech.LANG_NOT_SUPPORTED){
Log.e("TTS","Language not Supporter");
}
else{
speak.setEnabled(true);
}
}
else{
Log.e("TTS","Init Failed");
}
}
});
This is some information that may help you get TTS working on an android emulator.
When I first tried your code I got the LANG_NOT_SUPPORTED error but soon realized my particular emulator instance did not have an TTS engine installed.
To install a TTS engine with an emulator I then had to use an emulator with Google Play (only a small subset of the AVD emulators have them). From the Android Virtual Device Manager you can Create Virtual Device and see (under phone for example) a few with Play Store: Pixel 4, Pixel 3a, Pixel 3, Pixel, Nexus 5X, Nexus 5.
I then used the Nexus 5 with API 25. (I already had it created.)
With the the emulator running I can then see the Play Store app listed. Run the Play Store app as you would on a phone (you'll have to authenticate yourself with your google account just as you would on a phone). Use the search bar and search for "speech services by google" - and install this app if not already installed. This is one TTS engine example which worked for me. Since this is the only TTS engine installed it is also the default. So if you choose to load other engines then you would have select the proper engine. (The engine name is a package name such as com.google.android.tts.)
I then ran your code (slightly modified) as in the following. I added some diagnostics to list the available languages and variants. I also reviewed the available languages and regions here: https://cloud.google.com/speech-to-text/docs/languages and for example just chose "ar-iq" (but "ar" also worked).
Note your "ar-XA" is a language tag used for voices and not for the engine language.
TTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status==TextToSpeech.SUCCESS){
Set<Locale> avail = TTS.getAvailableLanguages();
for (Locale locale : avail) {
Log.e(TAG,"local: "+locale);
if (locale.getDisplayVariant() != null) {
Log.e(TAG," var: "+locale.getVariant());
}
}
List<TextToSpeech.EngineInfo> engineInfo = TTS.getEngines();
for (TextToSpeech.EngineInfo info : engineInfo) {
Log.e(TAG,"info: "+info);
}
int res = TTS.setLanguage(Locale.forLanguageTag("ar-iq"));
if (res == TextToSpeech.LANG_MISSING_DATA || res == TextToSpeech.LANG_NOT_SUPPORTED){
Log.e("TTS","Language not Supporter");
}
else{
//speak.setEnabled(true);
TTS.speak("اَلْعَرَبِيَّةُ", TextToSpeech.QUEUE_ADD, null);
}
}
else{
Log.e("TTS","Init Failed");
}
}
});
Once you have the TTS engine installed and your code or above code works - I think you can then use Settings to install your voice data:
Settings | Speech | Text-to-speech output | (choose Speech Services by Google) and select the gear icon | and select your voice data.
You could also use the voice data programmatically.
Note you can install another TTS engine (not the default) by using the constructor:
TextToSpeech(Context context, TextToSpeech.OnInitListener listener, String engine)
The Arabic voices which come with the Google TTS engine have the following language tags - I'm guessing that when the language is set a preferred voice is used which is one of these:
ar-xa-x-arz-local
ar-xa-x-arc-local

How to resolve setWifiEnabled(bool) deprecated method into Android Q?

In my case, I have existing code for enabling wifi. Here I am getting code depreciation at CONNECTIVITY_ACTION and setWifiEnabled(true) in Android Q api level 29. Below code is working fine in old version but depreciation happen only on api 29. How to resolve it with help of version condition.
Enable Wifi Code
private void enableWifi(Context context, String ssid) {
if(webWifiStateListener != null) {
context.unregisterReceiver(webWifiStateListener);
}
webWifiStateListener = new WifiStateListener(ssid);
context.registerReceiver(webWifiStateListener,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); // CONNECTIVITY_ACTION Deprecated Android Q
webWifiManager.setWifiEnabled(true); // Deprecated Android Q
}
Android Q won't let apps turn Wi-Fi on and off. You can use something like this https://developer.android.com/reference/android/provider/Settings.Panel
Use this in Android Q:
Intent panelIntent = new Intent(Android.Provider.Settings.Panel.ActionWifi);
StartActivityForResult(panelIntent,1);
Don't use:
webWifiManager.setWifiEnabled(true); // Deprecated Android Q

Why isOperational() in mobile vision text Recognizer in a device return true and in other return false?

Why isOperational() in mobile vision text recognizer returns false?
At first, mobile vision only show preview camera and after many tries to get the result, I saw that the texts recognized but in one device it works and in other device does not.
What should I do?
For example, in one device, isOperational() returns false, and it goes to readstate() and after that goes to looper() and stays on it!
in other device it only return false and doesn't go to looper.
I want ask other questions about it:
My first question is: how does isOperational() work? I can't understand it.
Maybe it goes to looper to download the native library in a queue and after many try, at last download completes and work. Can it be correct? Or is it just a bug that it goes to looper? Anywhere, what should I do?
Can I work on this when it works in one device I tried and in other does not? Or it must work in every device to I can work on it? And I get .apk from project but it can't install in devices, why?
Should it check for network?
Should it check for access to the memory?
note: it works with camera API and its deprecated. maybe the problem is with this!
TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build();
textRecognizer.setProcessor(new OcrDetectorProcessor(graphicOverlay));
if (!textRecognizer.**isOperational**()) {
// Note: The first time that an app using a Vision API is installed on a
// device, GMS will download a native libraries to the device in order to do detection.
// Usually this completes before the app is run for the first time. But if that
// download has not yet completed, then the above call will not detect any text,
// barcodes, or faces.
//
// isOperational() can be used to check if the required native libraries are currently
// available. The detectors will automatically become operational once the library
// downloads complete on device.
Log.w(TAG, "Detector dependencies are not yet available.");
// Check for low storage. If there is low storage, the native library will not be
// downloaded, so detection will not become operational.*
IntentFilter lowstorageFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW);
boolean hasLowStorage = registerReceiver(null, lowstorageFilter) != null;
if (hasLowStorage) {
Toast.makeText(this, R.string.low_storage_error, Toast.LENGTH_LONG).show();
Log.w(TAG, getString(R.string.low_storage_error));
}
}
*// Creates and starts the camera. Note that this uses a higher resolution in comparison
// to other detection examples to enable the text recognizer to detect small pieces of text.*
cameraSource =
new CameraSource.Builder(getApplicationContext(), textRecognizer)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedPreviewSize(1280, 1024)
.setRequestedFps(2.0f)
.setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null)
.setFocusMode(autoFocus ? Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO : null)
.build();
}
It doesn't produce any error and show preview camera but doesn't recognize texts in some devices.

How to detect check or identify app is running on Android Go edition 8.1 Device programatically

I'd like to disable some features and reduce memory consumption on Android Go Devices. I'd like to have one APK for all Android devices.
How do I detect that my app is running on an Android Go 8.1 Device?
Is it sufficient to check for version 8.1 or will 8.1 version be distributed to normal Android Devices as well?
This works for me, based on preinstalled Apps.
If Assistant Go or Google Go versions are installed, definitely is an Android Go device.
In rare cases that these apps didn't come preinstalled we look for Gmail Go and also Youtube Go preinstalled.
Tested on Huawei Y5 Lite with Android 8.1 (Go).
public static boolean isAndroidGoEdition(Context context) {
final String GMAIL_GO = "com.google.android.gm.lite";
final String YOUTUBE_GO = "com.google.android.apps.youtube.mango";
final String GOOGLE_GO = "com.google.android.apps.searchlite";
final String ASSISTANT_GO = "com.google.android.apps.assistant";
boolean isGmailGoPreInstalled = isPreInstalledApp(context, GMAIL_GO);
boolean isYoutubeGoPreInstalled = isPreInstalledApp(context, YOUTUBE_GO);
boolean isGoogleGoPreInstalled = isPreInstalledApp(context, GOOGLE_GO);
boolean isAssistantGoPreInstalled = isPreInstalledApp(context, ASSISTANT_GO);
if(isGoogleGoPreInstalled | isAssistantGoPreInstalled){
return true;
}
if(isGmailGoPreInstalled && isYoutubeGoPreInstalled){
return true;
}
return false;
}
private static boolean isPreInstalledApp(Context context, String packageName){
try {
PackageManager pacMan = context.getPackageManager();
PackageInfo packageInfo = pacMan.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
if(packageInfo != null){
//Check if comes with the image OS
int mask = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
return (packageInfo.applicationInfo.flags & mask) != 0;
}
} catch (PackageManager.NameNotFoundException e) {
//The app isn't installed
}
return false;
}
There doesn't seems to be direct api for retrieving whether app is running on GO version.
But you may cover the case by combination of following :
based on device memory and deciding on threshold value for your app:
private ActivityManager.MemoryInfo getAvailableMemory() {
ActivityManager activityManager =
(ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new
ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
Further similar steps can be take for particular model/manufacturer :
String deviceName = android.os.Build.MODEL;
String deviceMan = android.os.Build.MANUFACTURER;
Hope it helps.
No, as #chrylis pointed out, checking the version number wont help because there is a full Android version with the same number.
According to the documentation, to check whether the device is running Android Go you could call either
ActivityManager.isLowRamDevice();
or
PackageManager.hasSystemFeature("FEATURE_RAM_LOW");
Both will return true if the device is running Android Go edition, and false if it's running the regular Android.
I would rely on these APIs rather than checking for other Android Go edition system apps (like the android Go version of Gmail) because those apps may have been installed or uninstalled by the user, potentially triggering false positives or false negatives.
In my experience, is ActivityManager.isLowRamDevice() is equivalent to being an Android Go phone.
boolean isAndroidGo() {
return ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE))
.isLowRamDevice();
}
}
Although, the last time I looked in the documentation, I don't think it says anywhere, explicitly, that Android Go and isLowRamDevice() are equivalent.

Reliable way of detecting whether an Android app is running in 'BlueStacks'

I would like to ascertain at run-time inside an Android app whether it is running within the BlueStacks Android emulator. This is so I can modify the way the app runs when running inside BlueStacks.
BlueStacks does not support multi-touch so I want to implement an alternative to the standard pinch-to-zoom functionality my current app has.
E.g.
If (appIsRunningInBlueStacks){
mySurfaceView.enableMultiTouchAlternatives();
} else{
mySurfaceView.enableMultiTouchFeatures();
}
What is a reliable way of ascertaining the value of appIsRunningInBlueStacks?
EDIT Summary of answers to comments on question:
Ben, Taras, thanks for the suggestions. The Build.MODEL etc. values for BlueStacks are:
Model: "GT-I9100"
Manufacturer: "samsung"
Device: "GT-I9100"
Product: "GT-I9100"
This is the same model number as the Samsung Galaxy SII so it would not be ideal to use this for fear of treating all users with SIIs the same as those on BlueStacks.
CommonsWare, the app continues to run in BlueStacks even with the < uses-feature> for multitouch in the manifest. In fact (also answering iagreen's question)...
packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
... returns true! This is to be expected I suppose as the emulator is convinced it is a Samsung Galaxy SII!
Therefore we are still without a way of reliably detecting whether an app is running on BlueStacks without also throwing all Samsung Galaxy SII users in the same bucket. Any other ideas?
All the above methods are not working on BlueStacks 5. The correct way to do is checking if the path of /mnt/windows/BstSharedFolder exists. It is working fine on both BlueStacks 4 and 5.
fun checkFilesExist(files: Array<String>): Boolean {
files.forEach {
val file = File(it)
if (file.exists()) {
return true
}
}
return false
}
fun isBlueStacks(): Boolean {
val BLUE_STACKS_FILES = arrayOf(
"/mnt/windows/BstSharedFolder"
)
return checkFilesExist(BLUE_STACKS_FILES)
}
You can check that the Bluestacks shared folder exist
/sdcard/windows/BstSharedFolder
Boolean onBlueStacks()
{
File sharedFolder = new File(Environment
.getExternalStorageDirectory().toString()
+ File.separatorChar
+ "windows"
+ File.separatorChar
+ "BstSharedFolder");
if (sharedFolder.exists())
{
return true;
}
return false;
}
After trying all the suggested solutions available online we found the Google's SafetyNet Attestation API is the only solution for detecting VMs like BlueStack(any version) and NoxPlayer.
Apps that care about content piracy (and other security issues) can filter their availability on the Google Play like Netflix filters devices on the PlayStore.
The new “device catalog” section of the console includes an option
called “SafetyNet exclusion,” which can be used to prevent “devices
that fail integrity tests or those that are uncertified by Google,”
from downloading a specific app: among these would be rooted devices
and those running custom ROMs.
But there is a catch user will still find the APK from cross-sharing or other distribution systems, so the client must implement SafetyNet Attestation API on the app level.
How does it work?
SafetyNet examines software and hardware information on the device
where your app is installed to create a profile of that device. The
service then attempts to find this same profile within a list of
device models that have passed Android compatibility testing. The API
also uses this software and hardware information to help you assess
the basic integrity of the device, as well as the APK information of
the calling app. This attestation helps you to determine whether or
not the particular device has been tampered with or otherwise
modified.
It's an (easy to implement) paid API from the Google which allows 10,000 free hits per day as of now :\
If anyone is interested in detecting VMs by them self, these are the good papers available suggesting heuristic approaches :
Evading Android Runtime Analysis via Sandbox Detection
Rage Against the Virtual Machine:
Hindering Dynamic Analysis of Android Malware
My version of BlueStacks is reporting my Build.Model as GT-N7100.
Using: android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_RENDERER) I get Bluestacks.
It maybe too late but for the sake of others who have the same problem :
public boolean isRunningOnEmulator() {
return Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
|| "google_sdk".equals(Build.PRODUCT)
|| Build.PRODUCT.contains("vbox86p")
|| Build.DEVICE.contains("vbox86p")
|| Build.HARDWARE.contains("vbox86");
}
Based on Mr. Regis' answer, you can detect it when the shared folder is present. However in Bluestacks 4, using file.exists() will only return false. This is because the shared folder has no permissions (000 or ----------). But listing files in the directory will detect the folder.
String path = Environment.getExternalStorageDirectory().toString();
Log.d("FILES", "Path: " + path);
File directory = new File(path);
File[] files = directory.listFiles();
for (File file : files) {
if (file.getName().contains("windows")) {
Log.d("FILES", "windows file exists, it's a bluestacks emu");
}
}
This Will be unique.
There is no bluetooth device in Bluestack.
So try to get The Bluetooth Address string which is always 'null' on Bluestack or Any emulator.Make sure you are adding Bluetooth permission on your project manifest.
BluetoothAdapter m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String m_bluetoothAdd = m_BluetoothAdapter.getAddress();

Categories

Resources