Turning LED on/off on Android (Flutter) eventually causes ANR - android

Description
I'm developing the application which one of the features is turning LED on/off depending on the recorded sound rhythm (so it happens with a quite high frequency). I use Flutter but for this functionality I created my own Java code switching LED on:
CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try {
cameraManager.setTorchMode(cameraId, true);
} catch (#SuppressLint("NewApi") CameraAccessException e) {
//handle exception
}
And here is the similar code turing LED off:
CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try {
cameraManager.setTorchMode(cameraId, false);
} catch (#SuppressLint("NewApi") CameraAccessException e) {
//handle exception
}
When I start using LED, I get cameraID by:
private static String getCameraIdWithFlash(CameraManager cameraManager) throws CameraAccessException {
String cameraId = null;
for (String id : cameraManager.getCameraIdList()) {
Boolean hasFlashAvailable = cameraManager.getCameraCharacteristics(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
if (hasFlashAvailable != null && hasFlashAvailable) {
cameraId = id;
break;
}
}
return cameraId;
}
Problem
My code runs perfectly on most devices but I'm aware there is ANR for at least one device (Redmi Note 10 Pro with Android 11). After some time (like 10-40 minutes) of switching LED on/off continuously the screen freezes, and the user is seeing the system's ANR window. So app stops working actually. What's interesting, system's top bar buttons allowing to enable some options like wi-fi, LED etc. aren't working until the phone restart.
Unfortunately I have no access to the logs, so can't provide more details for the time being. But I wonder if that's the issue with my code or it's just related to Redmi phones or something. I believe it's rather not related to the Android version. I tested the app with Samsung Galaxy A71 Android 11 and couldn't reproduce the issue while it happens very often for Redmi Note 10 Pro.
I'd be grateful for any suggestions. Thank you!

Related

Error "Device doesn't support picture-in-picture mode" entering PIP (picture in picture) mode on Samsung mobile

I'm using PIP mode on Android O phone (various Samsung versions) and it works fine. However, if I turn on accessibility mode I get
java.lang.IllegalStateException·enterPictureInPictureMode: Device doesn't support picture-in-picture mode
when entering PIP mode. Before entering PIP I do check PackageManager.FEATURE_PICTURE_IN_PICTURE and if AppOpsManager.OPSTR_PICTURE_IN_PICTURE is enabled (both return true). The message "Device doesn't support picture-in-picture mode" is obviously misleading and wrong but is there any way to check if PIP is available in this case?
Note that this appears to be Samsung only problem as I tried various Samsung phones and tablets (S8, Note 8, Tab S3, Tab S4) and they all crashed. Google Pixel 3 phone did not have this problem.
I thoroughly went through the source code of related files but couldn't find any API visible to us. SO for now, I have placed a below solution, in case it helps you as well.
/**
* Trying to enter Picture In Picture mode on a Samsung device while an accessibility service
* that provides spoken feedback would result in an IllegalStateException.
*/
public static boolean isScreenReaderActiveAndTroublesome(Activity activity) {
final String affectedManufacturer = "samsung";
final String deviceManufacturer = android.os.Build.MANUFACTURER.toLowerCase();
if (affectedManufacturer.equals(deviceManufacturer)) {
final AccessibilityManager am =
(AccessibilityManager) activity.getSystemService(Context.ACCESSIBILITY_SERVICE);
final List<AccessibilityServiceInfo> enabledScreenReaderServices =
am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
final boolean isScreenReaderServiceActive = !enabledScreenReaderServices.isEmpty();
if (isScreenReaderServiceActive) {
Log.e(TAG, "Screen reader is active on this Samsung device, PIP would be disabled");
}
return isScreenReaderServiceActive;
}
return false;
}

Does BluetoothLeAdvertiser work on a Nexus 5 with Android 5.0?

After flashing my Nexus 5 to the Android 5.0 preview release hammerhead-lpx13d, the OS reports that it no longer supports Bluetooth LE advertising. If you call:
((BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE))
.getAdapter().getBluetoothLeAdvertiser()
always returns null. In addition, the new method:
((BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE))
.getAdapter().isMultipleAdvertisementSupported()
always returns false
The first method used to return a valid object on the first Android L preview release for the Nexus 5 back in June. It no longer does, after flashing the latest update.
Does anybody see otherwise?
EDIT: This has been reproduced by at least one person, who opened an issue with Google here: https://code.google.com/p/android-developer-preview/issues/detail?id=1570
Unfortunately, the official answer from Google is no, the Nexus 5 no longer supports advertising.
We introduced BLE peripheral mode in Android 5.0 Lollipop. Nexus 6 and
Nexus 9 are the first two production Nexus devices that support BLE
peripheral mode. Due to hardware chipset dependency, older Nexus
devices (4/5/7) will not have access to the feature on Lollipop.
See Comment #52 on issue 1570 by danielho...#google.com: BLE advertise mode not working
https://code.google.com/p/android-developer-preview/issues/detail?id=1570
That said, I have confirmed that advertising is supported by the Nexus 9 tablet. See here for details: http://developer.radiusnetworks.com/2014/11/18/beacon-transmission-with-android-5.html
This is not full a solution, but a proposed work-around posted by mattprec on Google Code. It allows you to get a BluetoothLeAdvertiser instance by calling the private constructor rather than using the public API. Unfortunately, reports of testing on a Nexus 5 and a Nexus 7 2013 edition say that even after you get an instance you can't use the object to make advertisements come out. Also, be warned that even if you can get it to work, it might break on any minor code release of Android because it is using a non-public API.
For the record, here's the code snippet copied from that page:
private static BluetoothLeAdvertiser getAdvertiserHack(BluetoothAdapter adapter) {
try {
Class<? extends BluetoothAdapter> adapterClass = adapter.getClass();
Field advertiserField = adapterClass.getDeclaredField("sBluetoothLeAdvertiser");
advertiserField.setAccessible(true);
Object advertiser = advertiserField.get(adapter);
if (advertiser == null) {
Field bluetoothManagerServiceField = adapterClass.getDeclaredField("mManagerService");
bluetoothManagerServiceField.setAccessible(true);
Object bluetoothManagerService = bluetoothManagerServiceField.get(adapter);
Constructor<?> constructor = BluetoothLeAdvertiser.class.getDeclaredConstructor(
bluetoothManagerServiceField.getType());
constructor.setAccessible(true);
advertiser = constructor.newInstance(bluetoothManagerService);
advertiserField.set(adapter, advertiser);
}
return (BluetoothLeAdvertiser) advertiser;
} catch (Exception e) {
return null;
}
}
That said, I have confirmed that advertising is supported by the Nexus
9 tablet. See here for details:
http://developer.radiusnetworks.com/2014/11/18/beacon-transmission-with-android-5.html
QuickBeacon app is working fine on Nexus 9. In app there is a Beacon Format option.#davidgyoung Could you give exact String for BeaconParser to make this library transmit in iBeacon format?
UPDATE:
Related question up to android-beacon-library/BLE Android SDK. Is there possibility - without calling startAdvertising method - to check if there is advertising service running in background?
UPDATE:
Recording to this : https://code.google.com/p/android-developer-preview/issues/detail?id=1570#c52
Now only Nexus 6 and Nexus 9 supports BLE Peripheal Mode in Android 5.0
UPDATE:
I work on Nexus 5 Android 5.0 build number LPX13D
according to this https://stackoverflow.com/a/26611779/1906420
After implementig your workaround bluetoothAdvertiser is not null. Calling startAdvertising from bluetoothAdvertiser
bluetoothAdvertiser.startAdvertising(settingsBuilder.build(), dataBuilder.build(), advertiseCallback);
where
private AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffec) {
}
#Override
public void onStartFailure(int result) {
if (result == ADVERTISE_FAILED_DATA_TOO_LARGE) {
Log.d(TAG, "Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.");
}
else if(result == ADVERTISE_FAILED_TOO_MANY_ADVERTISERS){
Log.d(TAG, "Failed to start advertising because no advertising instance is available.");
}
else if(result == ADVERTISE_FAILED_ALREADY_STARTED){
Log.d(TAG, "Failed to start advertising as the advertising is already started.");
}
else if(result == ADVERTISE_FAILED_INTERNAL_ERROR){
Log.d(TAG, "Operation failed due to an internal error.");
}
else if(result == ADVERTISE_FAILED_FEATURE_UNSUPPORTED){
Log.d(TAG, "This feature is not supported on this platform.");
}
else {
Log.d(TAG, "There was unknown error.");
}
}
};
always give callback onStartFailure with error code 5 ( ADVERTISE_FAILED_FEATURE_UNSUPPORTED )

startVoiceRecognition with bluetooth headset is not working

I need to use bluetooth headset with voice recognition, which almost works fine in some devices like S3, S4 and Samsung Grand. However, when I tried same on Nexus 7, I am getting
BluetoothHeadsetServiceJni : Failed to start voice recognition, status: 6
error when I am calling startVoiceRecognition() method. I am using the code from this SO page.
What are the possible reasons for this issue occur only in some devices? Is there any way to solve this issue?
Using shoe rat suggestion, modify the start method in the link and see if it will work.
public boolean start()
{
if (!mIsStarted)
{
mIsStarted = true;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB || "Nexus 7".equals(Build.MODEL)
{
mIsStarted = startBluetooth();
}
else
{
mIsStarted = startBluetooth11();
}
}
return mIsStarted;
}
I have been check as Narayan mentioned, I found BluetoothHeadset.STATE_AUDIO_CONNECTED does fire in nexus 7 as well some other ZTE devices, may be this is manufature fault or a that device does not support call and you are try to communicate via call_mode, I think there is only workaround to solve this issue
Nexus 7 does not support VoiceRecognition,becuase Nexus 7 does not support Bluetooth HFP(handsfreee profile) who contains VoiceRecognition.
You can find device Bluetooth info in https://www.bluetooth.org/tpg/listings.cfm.

How to check if camera is opened by any application

Is there any way to check if the camera is open or not? I don't want to open the camera, I just want to check its status.
If your device API version is higher than 21, CameraManager.AvailabilityCallback might be a good choice.
You need to first obtain the camera manager of the system with the following code:
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Then, you need to register the AvailabilityCallback:
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
manager.registerAvailabilityCallback(new CameraManager.AvailabilityCallback() {
#Override
public void onCameraAvailable(String cameraId) {
super.onCameraAvailable(cameraId);
//Do your work
}
#Override
public void onCameraUnavailable(String cameraId) {
super.onCameraUnavailable(cameraId);
//Do your work
}
}, yourHandler);
}
This works better if API version is higher than 21. You can refer to CameraManager, CameraManager.AvailabilityCallback, and the whole package
Trying to open the camera to check if exception is thrown works good if API level is lower than 23. In API level 23, camera service is different than before, from the official docs:
Access to camera subsystem resources, including opening and configuring a camera device, is awarded based on the “priority” of the client application process. Application processes with user-visible or foreground activities are generally given a higher-priority, making camera resource acquisition and use more dependable.
Active camera clients for lower priority apps may be “evicted” when a higher priority application attempts to use the camera. In the deprecated Camera API, this results in onError() being called for the evicted client. In the Camera2 API, it results in onDisconnected() being called for the evicted client.
We can see that in API 23 or higher, trying to open the camera used by other app/process will seize the camera from app/process which was using it, instead of getting RuntimeException.
You can check it using method Camera.open(cameraId).
Creates a new Camera object to access a particular hardware camera. If the same camera is opened by other applications, this will throw a RuntimeException.
Throws
RuntimeException
If opening the camera fails (For Example, if the camera is in use by another process or device policy manager has disabled the camera).
Update:
Example:
public boolean isCameraUsebyApp() {
Camera camera = null;
try {
camera = Camera.open();
} catch (RuntimeException e) {
return true;
} finally {
if (camera != null) camera.release();
}
return false;
}
You can use this method to use as Paul suggested but keep this thing in mind that this method first acquire the camera.
If its acquire successfully then its mean that no other application is using this camera and don't forgot to release it again otherwise you will not able to acquire it again.
Its its throws RuntimeException it means that camera is in use by another process or device policy manager has disabled the camera.
Looking into the source code of Camera, its JNI counterpart, and finally the native code for connecting a camera with the service, it appears that the only way of determining if the camera is in use is directly through the result of Camera::connect(jint).
The trouble is that this native code is only accessible through the JNI function android_hardware_Camera_native_setup(JNIEnv*, jobject, jobject, jint), which sets up the camera for use when creating the Camera instance from Java in new Camera(int).
In short, it doesn't seem possible. You'll have to attempt to open the camera, and if it fails, assume it is in use by another applicaiton. E.g.:
public boolean isCameraInUse() {
Camera c = null;
try {
c = Camera.open();
} catch (RuntimeException e) {
return true;
} finally {
if (c != null) c.release();
}
return false;
}
To better understand the underlying flow of camera's native code, see this thread.

How to detect android front camera programmatically

Can anyone tell me how to check if the android phone has a front camera too? I'd tried to use some help form https://docs.google.com/View?id=dhtsnvs6_57d2hpqtgr but Camera camera = FrontFacingCamera.getFrontFacingCamera(); sometimes works sometimes not.
Any help please?
Can anyone tell me how to check if the android phone has a front camera too?
There is no API for this, at least through Android 2.2. Sorry!
I'd tried to use some help form https://docs.google.com/View?id=dhtsnvs6_57d2hpqtgr but Camera camera = FrontFacingCamera.getFrontFacingCamera(); sometimes works sometimes not.
That is for two specific models of phones, not for Android devices in general. With luck, the upcoming Gingerbread release will add built-in support for front-facing cameras.
In the meantime, you need to get the instructions (like the one you linked to) from each and every device manufacturer and attempt to follow them.
private boolean hasFlash() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
try {
if(camManager==null)
camManager=(CameraManager)getSystemService( CAMERA_SERVICE );
String cameraId = camManager.getCameraIdList()[1];
CameraCharacteristics cameraCharacteristics = camManager.getCameraCharacteristics( cameraId );
return cameraCharacteristics.get( CameraCharacteristics.FLASH_INFO_AVAILABLE );
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}

Categories

Resources