Refrain the Use of Platform.isAndroid in Flutter — Runtime Platform Detection Made Right

UtkarshKore
3 min readMar 23, 2024

Yes, you read it right! Platform.isAndroid and Platform.isIOS are not the first choice when it comes to detecting runtime platforms for Flutter apps. Turns out, there are other better ways to detect which platform your app is currently running on —

Why Platform Class is Not The First Choice

Even though all the articles and YouTube tutorials show the use of Platform class for checking if platform is Android/iOS/Others, it is not recommended. Here are the reasons:

  • Platform.isAndroid and Platform.isIOS return false in a test environment. Hence, platform branching (platform if checks) code will fail for the test case.
  • Platform class is not mockable when writing Widget Tests. You cannot stub the behavior for underlying platform enums which makes it hard to test platform specific logic, if any.
Test Cases Failing
Photo by Alex Kondratiev on Unsplash

Hence, Platform class is easy and goto choice for beginner, non widget test projects. However, if you are planning to write tests you should use one of the methods below.

1. Using Theme Data

As we get text theme, screen and orientation data, in the same way, we can make use of platform property from Theme

final isAndroid = Theme.of(context).platform == TargetPlatform.android;

Arghh! Don’t tell I need to pass context everywhere through my nested code just to get the platform😶‍🌫️.

No, this is recommended way for widgets residing in the UI layer. For other business layers,

2. defaultTargetPlatform top-level property

Flutter directly provides a top-level property for accessing platform where context cannot reach (or extra effort). This is accessible from ‘package:flutter/foundation.dart’ package.

import 'package:flutter/foundation.dart';

if (defaultTargetPlatform == TargetPlatform.android) {
// android code
} else if(defaultTargetPlatform == TargetPlatform.iOS) {
// iOS code
} else if(kIsWeb) {
// web
} else {
// other platforms

// TargetPlatform.fuchsia
// TargetPlatform.linux
// TargetPlatform.macOS
// TargetPlatform.windows
}

3. Stub Platform in Unit/Widget Tests

Flutter provides a top-level field debugDefaultTargetPlatformOverride for stubbing platform behavior. It’s very simple to use:

testWidgets('test name',(WidgetTester tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
// target platform is now iOS
// test code
// ...
// ...
debugDefaultTargetPlatformOverride = null;
});

Remember, default platform is Android for defaultTargetPlatform field in widget tests.

Notice, how at the end of the test case, the override field is made null. This is important because testWidgets() calls function debugAssertAllFoundationVarsUnset() that will check whether debugDefaultTargetPlatformOverride is null to make sure you didn’t forget to reset it to the default value. This must be done because debugDefaultTargetPlatformOverride is a top-level variable that persists across tests.

Note : You might want to make debugDefaultTargetPlatformOverride = null in the tearDown(), but it won't work since debugAssertAllFoundationVarsUnset() is called before tearDown().

That’s it. I hope this article was helpful in some way or the other. Do comment if I have made any mistakes or better solution available.

Happy Coding…
Utterly Flutterly Declious!

Follow me on LinkedIn — Utkarsh Kore

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Responses (2)

Write a response

Platform.isAndroid and Platform.isIOS return false in a test environment.

That's kind of logical, isn't it :) ? The test environment is a test "platform", e.g. it's neither iOS, nor Android. However, I would expect if a test environment mocks an OS, to have these flags there.

Hi! How can I edit the behavior of kIsWeb on tests?