I have an web application where mobile phone users see a mobile optimized website. The new Samsung Galaxy SIII user agent provides no clue that the request is coming from a mobile phone. What are the best pratices to detect mobile phones?
I'm aware of javascript feature detection (ie. modernizer) but am hoping for something better. Below is the Samsung Galaxy SIII user agent:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
EDIT: The SIII has two possible user agents. Above is the 'desktop' version. Fun stuff. See link below for details.
http://www.anandtech.com/Show/Index/5310?cPage=19&all=False&sort=0&page=5&slug=samsung-galaxy-nexus-ice-cream-sandwich-review
Looking at that user agent, I'd have to say that, that would be extremely difficult to differentiate from a non-handheld device.
The problem with browser detection is that it's obviously easy to tweak the user agent string, and thus you never really know if what the server is telling you is honest or not.
You have two options in this case:
You can check every single header the phone sends and maybe see if there is one that could make it unique
Or find some type of work-around by testing page load time etc..., As a whimsical example, browsers on handheld devices usually render pages a bit slower than their desktop counterparts, so after testing every possible mobile device with something like:
-
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {
// some code..
}
You can see if a page with nothing else but a simple script is not loading in it's ideal time.
You get the point.
Also, try going here and see if it can detect you: http://detectmobilebrowsers.com/
The "desktop mode" user agent is designed so that the web server doesn't deliver a mobile/tablet interface when the user has deliberately chosen to have the desktop mode - it is a usability anti-pattern to remove that choice from the user.
If you absolutely *must* override the user's choice, then in JavaScript currently (2013) if all the following are true then it very likely is an Android device:
'ontouchstart' in document.documentElement
navigator.vendor === 'Google Inc.'
/^Linux armv/.test(navigator.platform)
However the above will give false positives and negatives with some less common browser setups e.g. an ARM based ChromeBook with touch, e.g. maybe Chromium running on Linux with an ARM processor (although perhaps that is Linux/ARM), e.g. maybe other browsers Firefox/Opera etc e.g. an Android device that is not touch based like a TV e.g. can Chrome run on Windows RT with an ARM processor? e.g. an Android running on Intel.
I have to detect "desktop view" after all, so similar to robocat's answer this is what I'm using to detect 'desktop view'. It's not perfect but it seems to provide the right balance of avoiding false positives:
if (userAgent.indexOf('X11; Linux x86_64') !== -1
&& 'ontouchstart' in document.documentElement
&& /^Linux armv/.test(navigator.platform)
&& _constructor.isChrome) {
if ((window.outerWidth < 500 && window.outerHeight < 800) || (window.outerWidth < 800 && window.outerHeight < 500)) {
// do stuff.
}
}
Helped me decide what the width / height filter should be
http://mydevice.io/devices/
http://viewportsizes.com/?filter=
Related
As part of some work I need to get done for Windows 10, I have written a code in C# that essentially detects every minute whether a PC is in screen saver mode or not, and it writes to a table in MySQL the relevant status ("PC in use" if the screen saver is off, "available PC" if the screen saver is on).
I did this using (full link if required - https://www.codeproject.com/Articles/17067/Controlling-The-Screen-Saver-With-C):
// Returns TRUE if the screen saver is actually running
public static bool GetScreenSaverRunning( )
{
bool isRunning = false;
SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0,
ref isRunning, 0 );
return isRunning;
}
The code works flawlessly in console application mode (I made a loop to test it out over a minute with a check up on screen save status every 10 seconds), this means in MySQL the status was set correctly every time, depending on the screen save status at the moment of the check up.
The problem occurs when I use this code for a windows service. The service is installed correctly, the log on tab is set on Local System (I also tried with the logged in user instead, same results) and I allow the service to interact with the desktop, just in case, but the difference here is that no matter if the PC enters screen save or not, it always returns false on GetScreenSaverRunning(), thus setting the status of the PC in MySQL as "PC in use", even if the screen saver is on at the moment of check up.
I get the sense that the problem isn't in the code itself, since it works without any issues as a console application, but perhaps something behind the scenes. I tried to search here and on many other websites, haven't found anything related to such a problem.
Does anyone have any idea at all what might be the issue? Any help and/or suggestions will be greatly appreciated!
Thank you in advance.
(I could post the code if required, but it is pretty much straight forward and the main part of it, controlling the screen save detection, is taken from the website mentioned above, afterwards it's a simple if (GetScreenSaverRunning() == true) )
Ever since Vista, Services are barred from a Interactive Session. Even if they run under the same rights, they do not get a interactive Session. I would guess that is getting in the way here.
While you can overwrite this behavior in the Service settings, this is not adviseable for new code. Consider making this a Background Task started by the Task Sheduler instead.
Because the windows service runs in different session then the windows logon. You can't interact with the desktop related services unless you run the windows service in win logon session. There used to be an option in Windows service manager where you can set the properties to "Interact with desktop session" but I don't think that ever worked.
There's a work around to run the windows service using the win logo session.
See this helper class that can get the current logged on user session and interact with the desktop services. https://github.com/murrayju/CreateProcessAsUser/blob/master/ProcessExtensions/ProcessExtensions.cs
Similar to this question which invokes the Windows 10 store to allow a user to write a review or rate an app, I'd also like to be able to invoke the Windows 10 Feedback app and allow users to provide feedback there.
I cannot seem to find much information on:
How this works in general. Can any old app use this service? (I
notice it just kind of shows whatever apps I have running)
How to invoke the Windows Feedback app with my package id
In short - not that I can see.
Other apps are invoked via protocol activation. I haven't seen this documented for the feedback app though so I have to err on the side of 'we haven't made this available yet' (I'm still checking though)
Here's an overall guide to the process http://blog.jerrynixon.com/2012/10/walkthrough-using-windows-8-custom.html?m=1
When I look in the registry under HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Protocol I see (shortened a tad)
[HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Protocol\PackageId\Microsoft.WindowsFeedback...\ActivatableClassId\App.AppX7eaybq6p4x7d4jgd6w6jk7r5dg6yhmbf.mca\CustomProperties]
"Name"="windows-feedback"
So - give that a try via launching windows-feedback
If I do Windows Key-R (run): windows-feedback://
it works fine so this should work:
var uri = new Uri(#"windows-feedback://");
var success = await Windows.System.Launcher.LaunchUriAsync(uri);
if (success)
{
// URI launched
}
else
{
// URI launch failed
}
Update
I've done some searching and it seems the magic parameter there is
windows-feedback:?contextid=522
That launches the NFL feedback for example. This is a predetermined number - I'm not sure how one gets on this list though.
I have a Surface Pro 4 that is being used in a medical environment and we would like to be able to disable to WiFi on the device when certain applications are running. Is this possible?
Disable is a relative term and as long as the device can't communicate over the wifi, even if technically active, that would meet the requirements. I wasn't able to find any way to do this though.
We could disable Wifi completely but would prefer to have it as an option for the users of the device when the specific applications aren't running.
The application in question is written in C#
You can do this with the Windows.Devices.Radios.Radio class by calling SetStateAsync(...).
There's a full example available at Microsoft's GitHub page, here's a snippet:
private async void SetRadioState(bool isRadioOn)
{
var radioState = isRadioOn ? RadioState.On : RadioState.Off;
Disable();
await this.radio.SetStateAsync(radioState);
NotifyPropertyChanged("IsRadioOn");
Enable();
}
Background
The company I work on is developing a kiosk-like application for tablets running Windows 8 Pro (on desktop mode). The user shouldn't be able to access anything that isn't the application itself: charms will be disabled, the taskbar will be hidden behind the application, etc.
This also means the user shouldn't be able to change network settings, leaving the responsability to keep the device always connected to us. Up to now, I had success using the Mobile Broadband API to assure the device is connected whenever there's a mobile network available. It'll detect disconnect events and try to connect again.
The Problem
Although the user shouldn't be able to do it, I'm considering the case where the user follows this steps:
User opens right-side charm,
clicks on Settings,
clicks on Network,
clicks on More PC Settings,
clicks on Wireless, and
disables the mobile broadband device.
I would like to be able to revert this programmatically and enable it again.
The Attempts
I have tried some different ways to force 3G being reenabled. Most of them give me the same result: they supposedly enable the device without errors, but I still cannot use it. Enable-NetAdapter in Powershell doesn't throw errors, and the Enable method of Win32_NetworkAdapter appears to work, but no dice.
I thought maybe the method IMbnRadio::SetSoftwareRadioState could be what I'm after, but I can't get to it when the device is disabled. The method IMbnInterfaceManager::GetInterfaces throws a COMException claiming the element could not be found (HRESULT = 0x80070490).
MbnInterfaceManager mbnInterfaceManager = new MbnInterfaceManager();
IMbnInterfaceManager interfaceManager = (IMbnInterfaceManager)mbnInterfaceManager;
// The following line throws a COMException:
IMbnInterface[] interfaces = (IMbnInterface[])interfaceManager.GetInterfaces();
mobileInterface = interfaces[0];
mobileRadio = (IMbnRadio)mobileInterface;
uint requestId;
mobileRadio.SetSoftwareRadioState(MBN_RADIO.MBN_RADIO_ON, out requestId);
Is there a way to override user preferences set on "More PC Settings?"
I found a sketchy way to solve this. Keep in mind this is undocumented, wrong, shameless and immoral, and will probably break eventually. The client is aware of this, but prefers to keep the access to the OS limited.
The setting in case is saved in the Registry. At least in the computers I've checked, it's stored in HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\0022 in a key named RadioOff.
The Airplane Mode setting is also stored in the Registry, but in a different place. It's at HKLM\SYSTEM\CurrentControlSet\Control\RadioManagement\SystemRadioState in a key named (Default).
After changing these keys and rebooting, everything seems to work fine. I'll repeat though: you really shouldn't be doing this, especially the Airplane Mode thing.
is there any way to check internet connection status in linux using mono
If it's desktop app, you could query NetworkManager (which is the network connection manager on most Linux desktops) over d-bus, using the NDesk.DBus library.
See Banshee for an example: http://git.gnome.org/cgit/banshee/tree/src/Core/Banshee.Services/Banshee.Networking/NetworkManager.cs
Apart from what Michael already suggested for a desktop application, you can also do something like:
foreach (NetworkInterface ni in NetworkInformation.GetAllNetworkInterfaces ()) {
// Check that any or all of:
// -ni.OperationalStatus == OperationalStatus.Up
// -that ni.NetworkInterfaceType is ethernet or wireless80211
// -ni.GetIPProperties() has a gateway and a DNS server
// ...
}
No matter what you end up using, it won't be reliable.
I see it all the time with Windows Vista and 7 at home. I use a home network, so my computers are always "connected." However, they are not always connected to the Internet.
That said, I would recommend checking the network interfaces as Gonzalo said. It is your best bet.
I would not rely on NetworkManager being present. I hate that thing and turn it off whenever I can. It is huge, ungainly, has an ugly name, relies on junk like HAL and DBUS. Early versions permanently put me off because they didn't work unless you were logged in to a GUI. It also collected bug work-arounds for wifi that were completely ridiculous in an open-source operating system that should have just fixed the original bugs. That led to other wifi managers and the command-line not being able to work properly and people being told to use NetworkManager, only because no one ever bothered to fix the actual bug!
You could try to open your connection as it is needed. If that fails display an error message.
Alternatively, if you really need a general check (e.g. at application start) you could try to make HTTP requests to one or more omnipresent websites like google.com. (Or what ever protocol you mean by "internet").
Check out HttpWebRequest.