← Back to posts Cover image for Flutter Tablet Exclusions: How to Target Phones Only on Android and Google Play

Flutter Tablet Exclusions: How to Target Phones Only on Android and Google Play

· 5 min read
Weekly Digest

The Flutter news you actually need

No spam, ever. Unsubscribe in one click.

Chris
By Chris

So you’ve built a Flutter app that’s designed for smartphones, but you’re finding it’s being installed on Android tablets where the experience isn’t great. Maybe your app relies on telephony features, or perhaps the UI just doesn’t scale well. You want to restrict it to phones only. Let’s walk through the most effective ways to achieve this, from store-level exclusions to runtime checks.

Why Target Phones Only?

Targeting phones only is often about user experience and functionality. Tablets often lack hardware like telephony modules. If your app is a dialer, SMS client, or uses call-related permissions, it might be useless on a Wi-Fi-only tablet. Alternatively, you might have a phone-specific UI that becomes awkward on a large screen. By restricting your app, you can avoid negative reviews from tablet users who can’t use your app as intended.

Method 1: The Store-Level Filter (Most Effective)

The most powerful approach is to tell the Google Play Store not to offer your app to tablets in the first place. This is done in your android/app/src/main/AndroidManifest.xml file by declaring a required hardware feature.

The most common and effective declaration is to require telephony hardware. Most tablets lack cellular capabilities, so this filter catches the vast majority of them.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <uses-feature android:name="android.hardware.telephony" android:required="true" />
    <!-- ... rest of your manifest ... -->
</manifest>

What this does: The android:required="true" attribute tells the Play Store, “Do not list this app on devices that do not have a telephony subsystem.” Users browsing on a Wi-Fi tablet will not see your app available for installation.

Important nuance: This method is excellent for filtering out most tablets, but be aware: some larger phones (“phablets”) have telephony, and a small number of cellular-enabled tablets will slip through. If you need a 100% guarantee, you’ll need to combine this with a runtime check (Method 3).

Method 2: Using Screen Density Features (A More Subtle Approach)

Another AndroidManifest.xml tactic is to use the android.hardware.screen.portrait feature. The logic here is that while tablets often support both orientations, phones are typically held in portrait mode for most apps. You can suggest a preference.

<uses-feature android:name="android.hardware.screen.portrait" android:required="false" />

Setting required="false" here is key. It tells the Play Store, “My app works best in portrait, but it can technically run otherwise.” The store may use this as a secondary signal for filtering, but it’s not a hard block. This method is less reliable than the telephony requirement and is best used as a supplementary hint.

Method 3: The Runtime Check (For Granular Control)

Sometimes, you need more control. Perhaps your app can run on a tablet, but you want to show a tailored message or redirect users to a tablet-optimized version of your service. This is where a Flutter runtime check comes in.

The classic heuristic is to check the shortestSide of the device screen. The general rule of thumb is that a shortestSide less than 600 logical pixels indicates a phone-sized device.

Here’s a simple utility function you can place in your app’s startup logic (e.g., in main() or your initial screen’s initState):

import 'package:flutter/widgets.dart';

bool _isLikelyTablet(BuildContext context) {
  final double shortestSide = MediaQuery.of(context).size.shortestSide;
  // Using 600 logical pixels as the threshold.
  return shortestSide >= 600;
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Builder(
        builder: (context) {
          // Perform the check once the context is available.
          if (_isLikelyTablet(context)) {
            return const Scaffold(
              body: Center(
                child: Text(
                  'This app is optimized for smartphones. '
                  'Please use your phone to install and run this application.',
                  textAlign: TextAlign.center,
                  style: TextStyle(fontSize: 18),
                ),
              ),
            );
          }
          // Otherwise, run the normal phone app.
          return const PhoneHomeScreen();
        },
      ),
    );
  }
}

Is shortestSide >= 600 reliable? It’s a good rule of thumb for Android, but it’s not perfect. Device pixel densities and aspect ratios vary. Some small tablets might dip below 600, and some very large phones might go above it. Use this as a soft filter in combination with the Manifest method, not as a sole solution.

Common Mistakes & Best Practices

  1. Over-reliance on runtime checks alone: If you only use a MediaQuery check, your app will still be installable on tablets, leading to potential confusion and bad reviews. Always start with the AndroidManifest.xml uses-feature filter.
  2. Forgetting about cellular tablets: The telephony filter won’t block LTE/5G tablets. If this is a critical issue for your app, your runtime check must be robust and you should consider showing a clear, informative message to those users.
  3. Testing on emulators: When you add <uses-feature android:name="android.hardware.telephony" android:required="true" />, your app might not install on a tablet or Wi-Fi-only emulator. Test your runtime logic on a phone emulator or a real device.

How This Affects Google Play Console

When you upload an APK or App Bundle with android.hardware.telephony set to required="true", the Play Console’s device catalog will automatically reflect this. Under “Device compatibility” in your release dashboard, you’ll see tablets largely excluded.

Final Recommendation

For the strongest phone-only targeting, use a two-tiered approach:

  1. Primary Gate: Add <uses-feature android:name="android.hardware.telephony" android:required="true" /> to your AndroidManifest.xml. This handles the store-level exclusion for ~95% of cases.
  2. Secondary Gate: Implement a runtime shortestSide check in your Flutter code. For the small percentage of devices that get past the first filter (like cellular tablets), you can display a friendly, explanatory message guiding users to the appropriate experience.

This combination gives you control at both the distribution and runtime levels, ensuring a clear path for your intended phone users and a graceful handling of everyone else.

This blog is produced with the assistance of AI by a human editor. Learn more

Related Posts

Cover image for Flutter's Hidden Gem: Building Powerful Linux Desktop Apps with Ease

Flutter's Hidden Gem: Building Powerful Linux Desktop Apps with Ease

Flutter is gaining traction as a robust framework for Linux desktop development, offering a smoother experience compared to traditional toolkits like GTK and Qt. This post will explore why Flutter excels for Linux apps, highlight its advantages, and provide practical insights for developers looking to leverage Flutter for their desktop projects.

Cover image for Simplifying Flutter Desktop Deployment: Signing and Distribution for Windows

Simplifying Flutter Desktop Deployment: Signing and Distribution for Windows

Deploying Flutter desktop apps on Windows can be challenging, especially regarding code signing and preventing Windows from blocking installations. This post will guide developers through the process of signing their Flutter desktop applications, exploring alternatives to the Microsoft Store like creating executable installers, and covering the necessary steps to ensure a smooth user experience.

Cover image for Mastering Flutter Tooling: Streamlining SDK Management and Installation on Windows

Mastering Flutter Tooling: Streamlining SDK Management and Installation on Windows

Developers frequently voice frustrations about Flutter SDK version management and installation processes, particularly on Windows. This post will explore best practices for managing multiple Flutter versions using tools like FVM, discuss integrating Flutter with package managers like Winget for a smoother Windows setup, and offer strategies to ensure a consistent development environment across projects and teams.