Determine if the device is a smartphone or tablet?

AndroidDevice Detection

Android Problem Overview


I would like to get info about a device to see if it's a smartphone or tablet. How can I do it?

I would like to show different web pages from resources based on the type of device:

String s="Debug-infos:";
s += "\n OS Version: " + System.getProperty("os.version") + "(" +    android.os.Build.VERSION.INCREMENTAL + ")";
s += "\n OS API Level: " + android.os.Build.VERSION.SDK;
s += "\n Device: " + android.os.Build.DEVICE;
s += "\n Model (and Product): " + android.os.Build.MODEL + " ("+ android.os.Build.PRODUCT + ")";

However, it seems useless for my case.


This solution works for me now:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
int height = metrics.heightPixels;

if (SharedCode.width > 1023 || SharedCode.height > 1023){
   //code for big screen (like tablet)
}else{
   //code for small screen (like smartphone)
}
        

Android Solutions


Solution 1 - Android

This subject is discussed in the Android Training:

Use the Smallest-width Qualifier

If you read the entire topic, they explain how to set a boolean value in a specific value file (as res/values-sw600dp/attrs.xml):

<resources>
    <bool name="isTablet">true</bool>
</resources>

Because the sw600dp qualifier is only valid for platforms above android 3.2. If you want to make sure this technique works on all platforms (before 3.2), create the same file in res/values-xlarge folder:

<resources>
    <bool name="isTablet">true</bool>
</resources>

Then, in the "standard" value file (as res/values/attrs.xml), you set the boolean to false:

<resources>
    <bool name="isTablet">false</bool>
</resources>

Then in you activity, you can get this value and check if you are running in a tablet size device:

boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
if (tabletSize) {
    // do something
} else {
    // do something else
}

Solution 2 - Android

I consider a tablet to have at least a 6.5 inch screen. This is how to compute it, based on Nolf's answer above.

DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);

float yInches= metrics.heightPixels/metrics.ydpi;
float xInches= metrics.widthPixels/metrics.xdpi;
double diagonalInches = Math.sqrt(xInches*xInches + yInches*yInches);
if (diagonalInches>=6.5){
    // 6.5inch device or bigger
}else{
    // smaller device
}

Solution 3 - Android

My assumption is that when you define 'Mobile/Phone' you wish to know whether you can make a phone call on the device which cannot be done on something that would be defined as a 'Tablet'. The way to verify this is below. If you wish to know something based on sensors, screen size, etc then this is really a different question.

Also, while using screen resolution, or the resource managements large vs xlarge, may have been a valid approach in the past new 'Mobile' devices are now coming with such large screens and high resolutions that they are blurring this line while if you really wish to know phone call vs no phone call capability the below is 'best'.

TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
		if(manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE){
			return "Tablet";
		}else{
			return "Mobile";
		}

Solution 4 - Android

I like Ol_v_er's solution and it's simplicity however, I've found that it's not always that simple, what with new devices and displays constantly coming out, and I want to be a little more "granular" in trying to figure out the actual screen size. One other solution that I found here by John uses a String resource, instead of a boolean, to specify the tablet size. So, instead of just putting true in a /res/values-sw600dp/screen.xml file (assuming this is where your layouts are for small tablets) you would put:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="screen_type">7-inch-tablet</string>
</resources>

Reference it as follows and then do what you need based on the result:

String screenType = getResources().getString(R.string.screen_type);
if (screenType.equals("7-inch-tablet")) {
	// do something
} else {
	// do something else
}

Sean O'Toole's answer for Detect 7 inch and 10 inch tablet programmatically was also what I was looking for. You might want to check that out if the answers here don't allow you to be as specific as you'd like. He does a great job of explaining how to calculate different metrics to figure out what you're actually dealing with.

UPDATE

In looking at the Google I/O 2013 app source code, I ran across the following that they use to identify if the device is a tablet or not, so I figured I'd add it. The above gives you a little more "control" over it, but if you just want to know if it's a tablet, the following is pretty simple:

public static boolean isTablet(Context context) {
    return (context.getResources().getConfiguration().screenLayout
            & Configuration.SCREENLAYOUT_SIZE_MASK)
            >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}

Solution 5 - Android

I use this method in all my apps, and it works successfully:

public static boolean isTablet(Context ctx){	
	return (ctx.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; 
}

Solution 6 - Android

Since tablet are in general bigger than smartphones and since a low res tablet may have the same number of pixels as a high res smartphone, one way to solve this is to calculate the physical SIZE (not resolution) of a device:

    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
   
    float yInches= metrics.heightPixels/metrics.ydpi;
    float xInches= metrics.widthPixels/metrics.xdpi;

   if (yInches> smallestTabletSize|| xInches > smallestTabletSize)
    {
                  //We are on a 
    }

Solution 7 - Android

The best option I found and the less intrusive, is to set a tag param in your xml, like

PHONE XML LAYOUT

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:tag="phone"/>

TABLET XML LAYOUT

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:tag="tablet">
    
    ...

</RelativeLayout>

and then call this in your activity class:

View viewPager = findViewById(R.id.pager);
Log.d(getClass().getSimpleName(), String.valueOf(viewPager.getTag()));

Hope it works for u.

Solution 8 - Android

The solution that I use is to define two layouts. One with the layout folder set to for example layout-sw600dp I use this to provide a menu button for my tablet users and to hide this for the phone users. That way I do not (yet) have to implement the ActionBar for my existing apps ...

See this post for more details.

Solution 9 - Android

Re: the tangent above on how to tell a phone from a non-phone: as far as I know, only a phone has a 15-digit IMEI (International Mobile Station Equipment Identity), so the following code will definitively distinguish a phone from a non-phone:

	TelephonyManager manager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
	String deviceInfo = "";
	deviceInfo += manager.getDeviceId(); // the IMEI
	Log.d(TAG, "IMEI or unique ID is " + deviceInfo);

	if (manager.getDeviceId() == null) {
		Log.d(TAG, "This device is NOT a phone");
	} else {
		Log.d(TAG, "This device is a phone.");
	}

I have found that on a Nook emulator getPhoneType() returns a phoneType of "GSM" for some reason, so it appears checking for phone type is unreliable. Likewise, getNetworkType() will return 0 for a phone in airplane mode. In fact, airplane mode will cause getLine1Number() and the getSim* methods to return null too. But even in airplane mode, the IMEI of a phone persists.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1001635View Question on Stackoverflow
Solution 1 - Androidol_v_erView Answer on Stackoverflow
Solution 2 - AndroidgtsoukView Answer on Stackoverflow
Solution 3 - AndroidRobert Dale Johnson IIIView Answer on Stackoverflow
Solution 4 - AndroidJasonView Answer on Stackoverflow
Solution 5 - AndroidJorgesysView Answer on Stackoverflow
Solution 6 - AndroidNolfView Answer on Stackoverflow
Solution 7 - AndroidAlejandro TellezView Answer on Stackoverflow
Solution 8 - AndroidStephanView Answer on Stackoverflow
Solution 9 - AndroidJohn UlmerView Answer on Stackoverflow