Android: PackageManager.getSystemAvailableFeatures() is not working as expected on Nexus9 - android

I am trying to get all the available system features on my Nexus9 device using PackageManager.getSystemAvailableFeatures().
From Android 5.0 Lollipop, Google introduced new camera APIs (camera2). I think Nexus9 is using Camera2 APIs.
When I am running this API on Nexus9 device it is not listing camera2 APIs features like:
android.hardware.camera.level.full
android.hardware.camera.capability.manual_post_processing
android.hardware.camera.capability.manual_sensor
android.hardware.camera.capability.raw
I am using below code to get all the available features:
public final static boolean isFeatureAvailable(Context context, String feature) {
final PackageManager packageManager = context.getPackageManager();
final FeatureInfo[] featuresList = packageManager.getSystemAvailableFeatures();
for (FeatureInfo f : featuresList) {
if (f.name != null && f.name.equals(feature)) {
return true;
}
}
return false;
}
Questions:
Is Nexus9 using & having camera2 API features?
If answer is yes for above question, then Why it is not listing these system level features? I am doing something wrong?
Thanks for your comments in advance!

Is Nexus9 using & having camera2 API features?
Yes. All Android Lollipop devices and newer have the camera2 APIs.
If answer is yes for above question, then Why it is not listing these system level features?
Supported APIs are usually not included in the system features list. Most system features are related to things that can vary from device to device and are usually related to hardware features (e.g. sensors, bluetooth, NFC, etc) or system-wide software support (e.g. backup, device management, multi-user, etc). There's a list of all supported capabilities here.
I am doing something wrong?
According to the docs, the recommended way to check if the camera2 APIs exist is by requesting the camera service via:
CameraManager cameraManager = (CameraManager) getSystemService("camera");
Basically this method returns null if the camera2 APIs aren't available, either because the version of Android is too old (sdkVersion < 21) or because they've been removed from the system (e.g. via a custom ROM).

Finally I was able to get answers to my questions.
Is Nexus9 using & having camera2 API features?
Ans: Yes Nexus9 is having and using Camera2 APIs. It has LIMITED supported hardware level and has capabilities: BACKWARD_COMPATIBLE and MANUAL_SENSOR
If answer is yes for above question, then Why it is not listing these system level features? I am doing something wrong?
Ans: Because using above code I am listing features not capabilities. To list down the capabilities I used below code:
Activity activity = getActivity();
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
if (characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) {
Log.d("Camera2 SUPPORTED_HARDWARE_LEVEL: ", "FULL");
} else if (characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
Log.d("Camera2 SUPPORTED_HARDWARE_LEVEL: ", "LEGACY");
} else if(characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
Log.d("Camera2 SUPPORTED_HARDWARE_LEVEL: ", "LIMITED");
}
StringBuilder stringBuilder = new StringBuilder();
for (int i=0; i<characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES).length; i++) {
if(characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)[i] ==CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
stringBuilder.append("BACKWARD_COMPATIBLE" + " ");
} else if (characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)[i] ==CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING) {
stringBuilder.append("MANUAL_POST_PROCESSING" + " ");
} else if(characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)[i] ==CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) {
stringBuilder.append("MANUAL_SENSOR" + " ");
} else if (characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)[i] ==CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW) {
stringBuilder.append("RAW" + " ");
}
}
Log.d("Camera2: ", stringBuilder.toString());

Related

How to play audio through earpiece in android 12?

I am developing a voice call app for android using PeerJS and WebView. And I want the audio to play through the earpiece. Here is my code,
private fun initAudio(){
am = getSystemService(AUDIO_SERVICE) as AudioManager
volumeControlStream = AudioManager.STREAM_VOICE_CALL
am.mode = AudioManager.MODE_IN_COMMUNICATION
am.isSpeakerphoneOn = false//<= not working in android 12
}
private fun toggleSpeakerMode(){
am.isSpeakerphoneOn = !am.isSpeakerphoneOn // <= final value is always true in android 12
}
The above code works fine on older versions of android, but not in android 12 (emulator).
am.isSpeakerphoneOn is always true in android 12. Am I doing something wrong here? Or is it a bug in the emulator?
there is a new API call in Android 12/S/API 31, setCommunicationDevice(AudioDeviceInfo). for switching between speaker an built-in earpiece now we can use:
ArrayList<Integer> targetTypes = new ArrayList<>();
if (earpieceMode) {
targetTypes.add(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE);
} else { // play out loud
targetTypes.add(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
}
// more targetTypes may be added in some cases
// set up will pick and first available, so order matters
List<AudioDeviceInfo> devices = audioManager.getAvailableCommunicationDevices();
outer:
for (Integer targetType : targetTypes) {
for (AudioDeviceInfo device : devices) {
if (device.getType() == targetType) {
boolean result = audioManager.setCommunicationDevice(device);
Log.i("AUDIO_MANAGER", "setCommunicationDevice type:" + targetType + " result:" + result);
if (result) break outer;
}
}
}
mode change isn't needed (but for voip calls is strongly suggested) and my streams are AudioManager.STREAM_VOICE_CALL type (where applicable)
By default webrtc uses earpiece for voice playing.
However,alternatively You can call the setSpeakerphoneOn(false) that is defined in the AudioManager.java class.
Just pass false in this function parameter and it will disable the speaker phone in the call and earpiece will be used.
I have also tested it on the android 12 phones and it is working fine.
If issue still persist then you have some bug in your emulator.

How to turn on the torch/flashlight with GooglePlay Services Vision API Xamarin Android

I have been trying to implement the flashlight/torch feature of the camera using the GooglePlay Services Vision API (using Nuget from Visual Studio) for the past few days without success. I have noticed that there is a GitHub implementation of this API which has such functionality but that is only available to Java users.
I was wondering if there is anything related to C# Xamarin users.
The Camera object is not made available on this API therefore I am not able to alter the Camera parameters needed to activate the flashlight.
I would like to be sure if that functionality is not available so I don't waste more time over this. It just might be the case that the Xamarin developers have not attended to this functionality and they might in a near future.
UPDATE
https://github.com/googlesamples/android-vision/blob/master/visionSamples/barcode-reader/app/src/main/java/com/google/android/gms/samples/vision/barcodereader/BarcodeCaptureActivity.java
In there you can see that on line 214 we have such method call:
mCameraSource = builder.setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null).build();
SetFlashMode is not a method of the CameraSource in Nuget, but it is on the GitHub (open source version).
Xamarin Vision Library Didn't expose the method to set Flash Mode.
WorkAround.
Using Reflection. You can get the Camera Object from CameraSouce and add the flash parameter then set the updated parameters to the camera.
This should be called after surfaceview has been created
Code
public Camera getCameraObject (CameraSource _camSource)
{
Field [] cFields = _camSource.Class.GetDeclaredFields ();
Camera _cam = null;
try {
foreach (Field item in cFields) {
if (item.Name.Equals ("zzbNN")) {
Console.WriteLine ("Camera");
item.Accessible = true;
try {
_cam = (Camera)item.Get (_camSource);
} catch (Exception e) {
Logger.LogException (this, e);
}
}
}
} catch (Exception e) {
Logger.LogException (this, e);
}
return _cam;
}
public void setFlash (bool isEnable)
{
try {
isTorch = !isEnable;
var _cam = getCameraObject (mCameraSource);
if (_cam == null) return;
var _pareMeters = _cam.GetParameters ();
var _listOfSuppo = _cam.GetParameters ().SupportedFlashModes;
_pareMeters.FlashMode = isTorch ? _listOfSuppo [0] : _listOfSuppo [3];
_cam.SetParameters (_pareMeters);
} catch (Exception e) {
Logger.LogException (this, e);
}
}
Basically, anything you can do with Android can be done with Xamarin.Android. All the underlying APIs area available.
Since you have existing Java code, you can create a binding project that enables you to call the code from your Xamarin.Android project. Here's a good article on how to get started: Binding a Java Library
On the other hand, I don't think you need a library to do what you want to. If you only want torch/flashlight functionality, you just need to adapt the Java code from this answer to work in Xamarin.Android with C#.

How to obtain display device characteristics in Android?

Folks,
Our application is intended to run only for a specific model of display monitor having a specific serial number. On Linux version of our app, we obtain this information via EDID.
We are now looking at porting the code over to Android (Google TV).
Is there any API on Android NDK that would let us obtain display device characteristics such as its model and serial number?
Thank you in advance for your help.
Regards,
Peter
Since Google TV devices don't have telephony hardware, you cannot use the TelephonyManager to get the device id.
You can get other device information using the following code:
Log.i(LOG_TAG, "android.os.Build.VERSION.RELEASE="+android.os.Build.VERSION.RELEASE);
Log.i(LOG_TAG, "android.os.Build.VERSION.INCREMENTAL="+android.os.Build.VERSION.INCREMENTAL);
Log.i(LOG_TAG, "android.os.Build.DEVICE="+android.os.Build.DEVICE);
Log.i(LOG_TAG, "android.os.Build.MODEL="+android.os.Build.MODEL);
Log.i(LOG_TAG, "android.os.Build.PRODUCT="+android.os.Build.PRODUCT);
Log.i(LOG_TAG, "android.os.Build.MANUFACTURER="+android.os.Build.MANUFACTURER);
Log.i(LOG_TAG, "android.os.Build.BRAND="+android.os.Build.BRAND);
For the Vizio Co-Star Google TV device you will get the following:
android.os.Build.VERSION.RELEASE=3.2
android.os.Build.VERSION.INCREMENTAL=U4.6.0-ota2
android.os.Build.DEVICE=VAP430
android.os.Build.MODEL=VAP430
android.os.Build.PRODUCT=StreamPlayer
android.os.Build.MANUFACTURER=VIZIO
android.os.Build.BRAND=Vizio
You can dump all the features using the following:
TextView text = (TextView) findViewById(id.featurestextview);
FeatureInfo features[] = getPackageManager()
.getSystemAvailableFeatures();
Log.d("Features", "getSystemAvailableFeatures() = " + features);
text.append("Supported System Features on this device:\n\n");
if (features != null) {
for (FeatureInfo featureInfo : features) {
if (featureInfo.name!= null) {
text.append(featureInfo.name+" (Flags: "+featureInfo.flags+") \n");
} else {
text.append(featureInfo+"\n");
}
}
}
long maxMemory = Runtime.getRuntime().maxMemory();
int memoryClass = ((ActivityManager) getSystemService(ACTIVITY_SERVICE)).getMemoryClass();
MemoryInfo memInfo = new MemoryInfo();
((ActivityManager) getSystemService(ACTIVITY_SERVICE)).getMemoryInfo(memInfo);
text.append("\n\nMEMORY:\nMaxMemory "+maxMemory/1024+"KB / "+maxMemory/1024/1024+"MB");
text.append(" (Memory Class: "+memoryClass+")");
text.append("\n MemoryInfo: Avail="+ memInfo.availMem / 1024 +"KB Threshold="+memInfo.threshold /1024 +"KB");
The android build properties for vendor etc will allow you to scope to a specific device. With respect to a serial number (eg. a cpu serial - is not available) we recommend you use the mac address.

Android: Check whether camera supports auto-focus?

For the Android API version 2.1 and higher, we can use context:
getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_AUTOFOCUS)
But before version 2.1, how can we perform the same operation? Is there anything like this that does not involve invoking Camera.open and then getParameters?
List<String> supportedFocusModes = camera.getParameters().getSupportedFocusModes();
boolean hasAutoFocus = supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)
i'm guessing: Do not use the unknown constant.
getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_AUTOFOCUS)
Should be:
getPackageManager().hasSystemFeature("android.hardware.camera.autofocus")
It was a short sight of the developers to use constants here. It solves the problem of knowing if a device, running an API that knows about a feature has a feature. but fails on the case you just mentioned... they really make supporting multiple api levels difficult.
Updated: just tested it myself... PackageManager.hasSystemFeature() only showed up at API level 5. I was trying to add that check to my code that can very well support API level 3 (1.5) but which could benefit from camera's auto focus...seems like i have to choose support 1.5 or be able to use auto focus... or move my backward compatibility to level 5... or implement this http://www.java.net/forum/topic/java-tools/java-development-tools/wwyt-conditional-compilation-pre-process ...yeah, right.
they really make it difficult to support multiple versions. So sorry 1.5 and 1.6 and 2.0 users. since my device is on 2.2 that will be my bottom line.
private void getSuppourtedFocusedModes(Camera camera)
{
final Camera.Parameters parameters = camera.getParameters();
List<String> supportedFocusModes = parameters.getSupportedFocusModes();
LogUtils.infoMsg("supportedFocusModes " + supportedFocusModes);
for (String mode : supportedFocusModes) {
LogUtils.infoMsg("supportedFocusModes " + mode);
}
}
CameraManager cameraManager = (android.hardware.camera2.CameraManager) getSystemService(CAMERA_SERVICE);
int[] afModes = cameraManager.getCameraCharacteristics("0").get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
if (afModes.length <= 1)
{Log.d(TAG, "Camera doesn't have autofocus");}
else
{Log.d(TAG, "Camera has autofocus");}
Log.d(TAG, "CONTROL_AF_AVAILABLE_MODES:");
for (int position : afModes) {
switch (afModes[position]) {
case 0:
Log.d(TAG, "CONTROL_AF_MODE_OFF (0)");
break;
case 1:
Log.d(TAG, "CONTROL_AF_MODE_AUTO (1)");
break;
case 2:
Log.d(TAG, "CONTROL_AF_MODE_MACRO (2)");
break;
case 3:
Log.d(TAG, "CONTROL_AF_MODE_CONTINUOUS_VIDEO (3)");
break;
case 4:
Log.d(TAG, "CONTROL_AF_MODE_CONTINUOUS_PICTURE (4)");
break;
case 5:
Log.d(TAG, "CONTROL_AF_MODE_EDOF (5)");
break;
default:
Log.d(TAG, String.valueOf(afModes[position]));
}
}
There are a number of methods of the Camera.Parameters class added in API Level 5 (I believe that maps to Android 2.0) that will return a list of supported features. Call getSupportedFocusModes on the Camera.Parameters object retrieved from camera.getParameters()
http://developer.android.com/reference/android/hardware/Camera.Parameters.html

Retrieving Android API version programmatically

Is there any way to get the API version that the phone is currently running?
As described in the Android documentation, the SDK level (integer) the phone is running is available in:
android.os.Build.VERSION.SDK_INT
The class corresponding to this int is in the android.os.Build.VERSION_CODES class.
Code example:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
// Do something for lollipop and above versions
} else{
// do something for phones running an SDK before lollipop
}
Edit: This SDK_INT is available since Donut (android 1.6 / API4) so make sure your application is not retro-compatible with Cupcake (android 1.5 / API3) when you use it or your application will crash (thanks to Programmer Bruce for the precision).
Corresponding android documentation is here and here
Very easy:
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
int version = Build.VERSION.SDK_INT;
String versionRelease = Build.VERSION.RELEASE;
Log.e("MyActivity", "manufacturer " + manufacturer
+ " \n model " + model
+ " \n version " + version
+ " \n versionRelease " + versionRelease
);
Output:
E/MyActivity: manufacturer ManufacturerX
model SM-T310
version 19
versionRelease 4.4.2
Build.VERSION.RELEASE;
That will give you the actual numbers of your version; aka 2.3.3 or 2.2.
The problem with using Build.VERSION.SDK_INT is if you have a rooted phone or custom rom, you could have a non standard OS (aka my android is running 2.3.5) and that will return a null when using Build.VERSION.SDK_INT so Build.VERSION.RELEASE will work no matter using standard Android version or not !
To use it, you could just do this;
String androidOS = Build.VERSION.RELEASE;
try this:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
// only for gingerbread and newer versions
}
Taking into account all said, here is the code I use for detecting if device has Froyo or newer Android OS (2.2+):
public static boolean froyoOrNewer() {
// SDK_INT is introduced in 1.6 (API Level 4) so code referencing that would fail
// Also we can't use SDK_INT since some modified ROMs play around with this value, RELEASE is most versatile variable
if (android.os.Build.VERSION.RELEASE.startsWith("1.") ||
android.os.Build.VERSION.RELEASE.startsWith("2.0") ||
android.os.Build.VERSION.RELEASE.startsWith("2.1"))
return false;
return true;
}
Obviously, you can modify that if condition to take into account 1.0 & 1.5 versions of Android in case you need generic checker. You will probably end up with something like this:
// returns true if current Android OS on device is >= verCode
public static boolean androidMinimum(int verCode) {
if (android.os.Build.VERSION.RELEASE.startsWith("1.0"))
return verCode == 1;
else if (android.os.Build.VERSION.RELEASE.startsWith("1.1")) {
return verCode <= 2;
} else if (android.os.Build.VERSION.RELEASE.startsWith("1.5")) {
return verCode <= 3;
} else {
return android.os.Build.VERSION.SDK_INT >= verCode;
}
}
Let me know if code is not working for you.
android.os.Build.VERSION.SDK should give you the value of the API Level. You can easily find the mapping from api level to android version in the android documentation. I believe, 8 is for 2.2, 7 for 2.1, and so on.
SDK.INT is supported for Android 1.6 and up
SDK is supported for all versions
So I do:
String sdk_version_number = android.os.Build.VERSION.SDK;
Credits to: CommonsWare over this answer
Got it. Its using the getApplicationInfo() method of the Context class.
I generally prefer to add these codes in a function to get the Android version:
int whichAndroidVersion;
whichAndroidVersion= Build.VERSION.SDK_INT;
textView.setText("" + whichAndroidVersion); //If you don't use "" then app crashes.
For example, that code above will set the text into my textView as "29" now.
i prefer have the version as number to be handeled more easyway than i wrote this:
public static float getAPIVerison() {
Float f = null;
try {
StringBuilder strBuild = new StringBuilder();
strBuild.append(android.os.Build.VERSION.RELEASE.substring(0, 2));
f = new Float(strBuild.toString());
} catch (NumberFormatException e) {
Log.e("", "error retriving api version" + e.getMessage());
}
return f.floatValue();
}
I improved code i used
public static float getAPIVerison() {
float f=1f;
try {
StringBuilder strBuild = new StringBuilder();
strBuild.append(android.os.Build.VERSION.RELEASE.substring(0, 2));
f= Float.valueOf(strBuild.toString());
} catch (NumberFormatException e) {
Log.e("myApp", "error retriving api version" + e.getMessage());
}
return f;
}
Like this:
String versionRelease = BuildConfig.VERSION_NAME;
versionRelease :- 2.1.17
Please make sure your import package is correct ( import package your_application_package_name, otherwise it will not work properly).

Categories

Resources