How to check if the code is running in Android?

Since the same code will be running on Desktop AND Android version, sometimes I need to run platform specific code.

Is there some “synchronous” easy way to tell I’m running on Android?

Currently I’m using this ugly monstrosity which I would like to replace with something nicer:

// NOTE: platform info is not available from content scripts!
export let isAndroid = false;
// currently only Firefox can be Android
export const isAndroidPromise = $IS_FIREFOX && !$IS_THUNDERBIRD && browser.runtime.getPlatformInfo ?
  browser.runtime.getPlatformInfo().then(({os}) => isAndroid = os === 'android') :
  Promise.resolve(false);

Tampermonkey at the moment assumes that a device without hover functionality is a mobile device and it seems to work so far.

const isMobile = window.matchMedia('(hover: none)').matches
2 Likes

This is some serious out of box thinking :slight_smile: , I was not expecting CSS to come to save the day! :smiley:

But I’m slightly worried though. Isn’t there some Windows touch tablet that would match that query?
Also, from the “long term” point of view, this won’t work in service workers.

It’s great though that it works in content scripts!

EDIT:
Maybe we could ask for a new API, something like browser.extension.inAndroidContext, similar to:

Hm… I’m a bit hesitant about a inAndroidContext property since it bakes the concept of the host OS into the variable name. Something like inMobileContext has more promise, but it’s hard to determine what the line between true and false would mean here. Is an Android tablet a mobile device? Is an Android laptop? What about Android apps running on Windows machines or Chromebooks?

When trying to address handle similar issues on the web, developers are advised to use feature detection. Some solid guidance for web devs is shared in the Implementing feature detection and Browser detection using the user agent articles on MDN.

If you’d like, I’d be game to kick around some ideas about how you might approch implementing features either here or in an office hours session.

Good point.

So, what I’m actually looking for is not a inMobileContext, since screen size can be solved with CSS.

What I’m looking for is a “browser detection”. Since Firefox for Android is a different browser with limited API and restricted behavior that sometimes needs special handling.

For other browsers I’m using special “global variables” that are replaced during the build with my Webpack (since I’m submitting a different build for each store).

But for Android I don’t have that and using Promise is not always possible (like those “user-actions” handlers).

This really feels like a trivial thing that should be there somewhere. I mean, the source code is submitted to the single store and the store will push it to two browsers, but the source code can’t tell which one without resolving a promise first? :frowning:

The feature detection can be OK for some (simple) cases, but not all.

1 Like

Try top level await.

// First detect OS with top level await
const { os } = await browser.runtime.getPlatformInfo();
const isAndroid = os === 'android';

// Do other stuff afterwards
(async () => {
  console.log(isAndroid);
})();

That looks cool!

However, this looks like it will break the “top level event loop, event handlers registration requirement” for the non-persistent background scripts and service workers.

Then save it in storage.local or storage.session.

I’m currently doing this:

const IS_MOBILE = /\bMobile\b/.test(navigator.userAgent);
1 Like

This looks pretty good!

Those user-switcher addons won’t affect it, right? They only intercept HTTP(S) traffic.

And I suppose Firefox for Android will use it no matter where you install it, right?
For example TV or Raspberry Pi :slight_smile:.

And desktop Firefox won’t use it, no matter how “mobile” your desktop is, correct?

I can’t think of any issue so far, it looks stable and works also in service worker and content scripts!

Thank you Paul!

EDIT:
Actually, when you enable “Desktop site” in the main menu, the user agent string changes to:

Mozilla/5.0 (X11; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0

That’s not good :smiley:.

Those user-switcher addons won’t affect it, right? They only intercept HTTP(S) traffic.

On desktop, If I set https://addons.mozilla.org/en-US/firefox/addon/user-agent-string-switcher/ to spoof Firefox for Android, my extension is unaffected. But I’m only using background/popup scripts; it’s possible that content scripts would behave differently.

But I don’t have answers to all of your questions. It would be a good idea to test your extension with IS_MOBILE inverted, to make sure nothing is catastrophically broken. I’m only using the value for minor UI tweaks.

1 Like