Detect if Android device uses navigational control - android

This is something I've been struggling with for quite some time. A lot of Chinese Android manufacturers create Android TV boxes that are controlled using a remote with keypad controls.
I'm looking for a definitive way of detecting if the device uses navigational controls or if it is in fact using touch screen input. Certain devices might emulate touch screen input as mouse input as well, so it's kind of tricky.
Any ideas?

Please read about input controls in the following articles:
http://developer.android.com/training/keyboard-input/index.html
http://developer.android.com/training/keyboard-input/navigation.html
http://developer.android.com/training/tv/optimizing-navigation-tv.html
To see at run-time what types of navigation a user has available, use the Configuration class.
Configuration configuration = context.getResources().getConfiguration();
if (Configuration.NAVIGATION_NONAV == configuration.navigation) {
// Device has no navigation facility other than using the touchscreen.
} else if (Configuration.NAVIGATION_DPAD == configuration.navigation) {
// Device has a directional-pad (d-pad) for navigation.
} else if (Configuration.NAVIGATION_TRACKBALL == configuration.navigation) {
// Device has a trackball for navigation.
} // ... etc

Based on Jozua's answer, I created this simple method which can be used to determine if a device uses navigation controls from a number of factors. The code is written in a way that attempts to fail early.
/**
* Determines if the device uses navigation controls as the primary navigation from a number of factors.
* #param context Application Context
* #return True if the device uses navigation controls, false otherwise.
*/
public static boolean usesNavigationControl(Context context) {
Configuration configuration = context.getResources().getConfiguration();
if (configuration.navigation == Configuration.NAVIGATION_NONAV) {
return false;
} else if (configuration.touchscreen == Configuration.TOUCHSCREEN_FINGER) {
return false;
} else if (configuration.navigation == Configuration.NAVIGATION_DPAD) {
return true;
} else if (configuration.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH) {
return true;
} else if (configuration.touchscreen == Configuration.TOUCHSCREEN_UNDEFINED) {
return true;
} else if (configuration.navigationHidden == Configuration.NAVIGATIONHIDDEN_YES) {
return true;
} else if (configuration.uiMode == Configuration.UI_MODE_TYPE_TELEVISION) {
return true;
}
return false;
}
I have tested this on numerous phones, tablets, emulator configurations and Google TV. A number of devices are controlled using a remote control and a USB mouse. I haven't yet tested whether it works as expected on such devices.

Related

Stop pre-installed screen recording apps from recording screen in android

I am using flutter and have disabled normal apps from recording the screen.
Here is the code
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
The problem is there are some phones where screen recordings apps are pre-installed and above code can't stop them from recording the screen.
So is there any other way to stop these apps from recording the screen?
On other answers I saw that this was not possible but there are some apps on playstore which successfully achieve this. So there must be a way.
I was thinking, as screen recording apps are drawn over , they might be detected through a piece of code hence we can show a pop up while screen recording app is drawn over.
Is it possible ? If yes how can we detect if the app is drawn over our app.
Thanks.
As far as I'm aware, there is no official way to universally prevent screen grabs/recordings.
This is because FLAG_SECURE just prevents capturing on non-secure displays:
Window flag: treat the content of the window as secure, preventing it from appearing in screenshots or from being viewed on non-secure displays.
But apps that have elevated permissions can create a secure virtual display and use screen mirroring to record your screen, which does not respect the secure flag.
Read this article for more info:
That would mean that an Android device casting to a DRM-protected display like a TV would always display sensitive screens, since the concept of secure really means “copyrighted”. For apps, Google forestalled this issue by preventing apps not signed by the system key from creating virtual “secure” displays
Regarding how some apps still manage to do it, you could try these:
Check if there are any external/virtual displays connected, and hide/show your content based on that. see this
Don't show your content on rooted devices
Adding this code to my MainActivity.java solved the problem:
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!this.setSecureSurfaceView()) {
Log.e("MainActivity", "Could not secure the MainActivity!");
}
}
private final boolean setSecureSurfaceView() {
ViewGroup content = (ViewGroup) this.findViewById(android.R.id.content);
//Intrinsics.checkExpressionValueIsNotNull(content, "content");
if (!this.isNonEmptyContainer((View) content)) {
return false;
} else {
View splashView = content.getChildAt(0);
//Intrinsics.checkExpressionValueIsNotNull(splashView, "splashView");
if (!this.isNonEmptyContainer(splashView)) {
return false;
} else {
View flutterView = ((ViewGroup) splashView).getChildAt(0);
//Intrinsics.checkExpressionValueIsNotNull(flutterView, "flutterView");
if (!this.isNonEmptyContainer(flutterView)) {
return false;
} else {
View surfaceView = ((ViewGroup) flutterView).getChildAt(0);
if (!(surfaceView instanceof SurfaceView)) {
return false;
} else {
((SurfaceView) surfaceView).setSecure(true);
this.getWindow().setFlags(8192, 8192);
return true;
}
}
}
}
}
private final boolean isNonEmptyContainer(View view) {
if (!(view instanceof ViewGroup)) {
return false;
} else {
return ((ViewGroup) view).getChildCount() >= 1;
}
}
Import the required things.

When exactly is the NFC Service deactivated?

I am wondering when exactly the NFC Service is started and stopped.
The source code for android 4.0.3 seems to state that the polling is dependent on a single constant (located in NfcService.java)
/** minimum screen state that enables NFC polling (discovery) */
static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED;
I would interpret this as "the screen light is on, therefore the nfc service is active".
BUT when the screen is locked, a NFC Tag wont be recognized, altough the screen is lit.
So I am curious: Is the NFC Service already deactivated when the lock screen appears, or is it still running but not processing the Tags?
Actually, I do not think that NFC Service is deactivated. When the screen has lower value then SCREEN_STATE_ON_UNLOCKED a device stops to ask NFC tags around. You can see this from this code:
// configure NFC-C polling
if (mScreenState >= POLLING_MODE) {
if (force || !mNfcPollingEnabled) {
Log.d(TAG, "NFC-C ON");
mNfcPollingEnabled = true;
mDeviceHost.enableDiscovery();
}
} else {
if (force || mNfcPollingEnabled) {
Log.d(TAG, "NFC-C OFF");
mNfcPollingEnabled = false;
mDeviceHost.disableDiscovery();
}
}
But NFC-EE routing is enabled util screen state is higher then SCREEN_STATE_ON_LOCKED:
// configure NFC-EE routing
if (mScreenState >= SCREEN_STATE_ON_LOCKED &&
mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
if (force || !mNfceeRouteEnabled) {
Log.d(TAG, "NFC-EE ON");
mNfceeRouteEnabled = true;
mDeviceHost.doSelectSecureElement();
}
} else {
if (force || mNfceeRouteEnabled) {
Log.d(TAG, "NFC-EE OFF");
mNfceeRouteEnabled = false;
mDeviceHost.doDeselectSecureElement();
}
}
The service itself is started and stopped in other parts of this class.
See related http://forum.xda-developers.com/showthread.php?t=1712024&page=14

Two checks of Content Resolver for Allow Mock Locations providing different results

I have the following code that evaluates to true in the emulator (OS 2.3.3) when "applications > settings > development > allow mock locations" is unchecked. I would expect the method to return false but it returns true.
public static boolean isMockLocationSet(Context context) {
if (Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) {
return false;
}
else {
return true;
}
}
The following change returns false, as expected (BTW what is better .equals or .ContentEquals?):
public static boolean isMockLocationSet(Context context) {
if (Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0")) { //.contentEquals("0")
return false;
}
else {
return true;
}
}
I prefer the first example because it should allow for cases where a null value may exist, assigning a default of 0 and still allowing execution of the logic without failure (in fact, I suspect this case may exist but have not proved it - e.g. a manufacturer implements Android without all the these settings established (i.e. some like Allow Mock Locations would begin their life as null)...waiting until a user check's the setting before writing a 1 (or 0 when unchecked) to the table).
So what is the problem? Well, I get the feeling from bug reports that different devices handle this check differently but not having access to all device types, I am looking for recommendations on how to handle generically / the best. Also, why would the first example not work?
Well I decided to simply use the following check:
public static boolean isMockLocationSet(Context context) {
if (Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).contentEquals("1")) {
return true;
}
else {
return false;
}
}
This method, of course, deals with the null case appropriately--returning false.
I cannot say why the code in the original question does not work...maybe a bug in the SDK.

android keyboard open issue

How can i know if the keyboard is open or not?
This is available on the Configuration class. You can get the current Configuration via getResources().getConfiguration() from your Activity or other Context.
That way =)
public boolean isKeyboardVisible(){
// Checks whether a hardware keyboard is visible
if (getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
return true;
} else if (getResources().getConfiguration()..hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
return false;
}
}

Camera.Parameters.FLASH_MODE_TORCH replacement for Android 2.1

I am trying to write an app that requires the LED flash to go into torch mode. The problem is, Android 2.1 does not support this mode and therefore I cannot support the platform yet. Wouldn't be an issue, but I am writing it for my fiance and her Epic 4G only has 2.1 right now. I found some code samples that use some undocumented API calls and therefore work on the Motorola Droid and such, but they do not work on the Epic. Does anyone have some suggestions on where to look to find code that should help me get this working?
I'm finding that torch mode is generally working fine on 2.1 but I had the same problem with the Samsung Epic and found a hack around it.
Looking at the params returned by Camera.getParameters() when run on the Samsung Epic, I noticed that the flash-modes it claims to support are: flash-mode-values=off,on,auto;
torch-mode is not listed, implying it's not supported.
However, I found that this model would still accept that mode and WOULD turn the LED on! The bad news was that when later setting the flash-mode back to auto or off left the LED still lit! It will not turn off until you call Camera.release().
I guess that's why Samsung dont include it in the list of supported!?!
So...the method I use to toggle torch in a CameraHelper class is...
/***
* Attempts to set camera flash torch/flashlight mode on/off
* #param isOn true = on, false = off
* #return boolean whether or not we were able to set it
*/
public boolean setFlashlight(boolean isOn)
{
if (mCamera == null)
{
return false;
}
Camera.Parameters params = mCamera.getParameters();
String value;
if (isOn) // we are being ask to turn it on
{
value = Camera.Parameters.FLASH_MODE_TORCH;
}
else // we are being asked to turn it off
{
value = Camera.Parameters.FLASH_MODE_AUTO;
}
try{
params.setFlashMode(value);
mCamera.setParameters(params);
String nowMode = mCamera.getParameters().getFlashMode();
if (isOn && nowMode.equals(Camera.Parameters.FLASH_MODE_TORCH))
{
return true;
}
if (! isOn && nowMode.equals(Camera.Parameters.FLASH_MODE_AUTO))
{
return true;
}
return false;
}
catch (Exception ex)
{
MyLog.e(mLOG_TAG, this.getClass().getSimpleName() + " error setting flash mode to: "+ value + " " + ex.toString());
}
}
The activities that use this call it as follows...
private void toggleFlashLight()
{
mIsFlashlightOn = ! mIsFlashlightOn;
/**
* hack to fix an issue where the Samsung Galaxy will turn torch on,
* even though it says it doesnt support torch mode,
* but then will NOT turn it off via this param.
*/
if (! mIsFlashlightOn && Build.MANUFACTURER.equalsIgnoreCase("Samsung"))
{
this.releaseCameraResources();
this.initCamera();
}
else
{
boolean result = mCamHelper.setFlashlight(mIsFlashlightOn);
if (! result)
{
alertFlashlightNotSupported();
}
}
}
The magic that makes this work in releaseCameraResources() is that it calls Camera.release()....and then I have to reinitialize all my camera stuff for Samsung devices.
Not pretty but seems to be working for plenty of users.
Note that I do have a report of torch mode not working at all with this code on Nexus one but have been able to dig into it. It definitely works on HTC EVO and Samsung Epic.
Hope this helps.
In my case for Samsung devices I needed to set focus mode to infinity and it started to work
params.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
mCamera.setParameters(params);
mCamera.startPreview();

Categories

Resources