315

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)
}
Blo
  • 11,903
  • 5
  • 45
  • 99
user1001635
  • 3,262
  • 3
  • 16
  • 17
  • using displaymetris get your screen size and do it. – Padma Kumar Feb 14 '12 at 15:01
  • 2
    Find the screensize is the only way. You can't really think of it in terms of "smartphone" and "tablet". In the end, screensize is what you want anyway. – DeeV Feb 14 '12 at 15:02
  • http://stackoverflow.com/a/8413440/265167 – Yaqub Ahmad Feb 14 '12 at 15:28
  • are your differences only layout-based? or do you plan to give completely different contents? Multiple layouts and Activities vs. Fragments are your way. – STT LCU Feb 16 '12 at 08:30
  • 2
    Using physical pixels is a horrible idea, as devices are getting more and more pixel-dense. At least you should use dp as unit. – cprcrack Dec 17 '14 at 12:19
  • You generally don't need to know if the device is a phone or tablet. Just provide different resource files for different screen sizes and let the system determine it for you. See [this answer](http://stackoverflow.com/a/41646301/3681880) for more. – Suragch Jan 14 '17 at 02:53
  • The official Android Developers blog posted a blog entry with the title 'Detecting device type – How to know if a device is foldable or a tablet'. This should answer this question as they clarify how to check if a device is a phone, a tablet or a foldable. SPOILER: As of June 2023 they check if at least one display has a sw >= 600 dp. Then it's a tablet or a foldable, otherwise it's classisfied as a phone. https://android-developers.googleblog.com/2023/06/detecting-if-device-is-foldable-tablet.html – Cyb3rKo Jul 16 '23 at 09:32

9 Answers9

852

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
}
Malwinder Singh
  • 6,644
  • 14
  • 65
  • 103
ol_v_er
  • 27,094
  • 6
  • 48
  • 61
  • 3
    Good answer! Very Brillant but in my case, i developing a library, i cant change/add any file/directory to the project – Aracem Sep 27 '12 at 09:07
  • 8
    This answer is good but possibly a bit dated since values-xlarge is now being deprecated.Using /res/values and /res/values-sw600 as the folders to store these values in may be a better solution. sw600 means "smallest width 600". If the size of the smallest dimension of the screen is greater than or equal to 600dp, the value in that folder will be chosen. A good reference for values and layout buckets (folders) is here: http://android-developers.blogspot.com/2012/07/getting-your-app-ready-for-jelly-bean.html. – javahead76 Feb 26 '13 at 17:11
  • You are right, now you have to use the sw600 qualifier instead of xlarge. But to keep compatibility with versions below android 3.2, you need to keep the boolean value in the xlarge resources folder. I added the precision in the answer. Thanks. – ol_v_er Feb 26 '13 at 19:01
  • 2
    Better **values-large** than **values-xlarge**. The old "large" is move equivalent to the new "sw600dp", to my understanding. – cprcrack Apr 25 '13 at 08:41
  • 8
    this may not work as effective any more as many smartphones now have minimum width>600, for example Samsung galaxy s3 which has min width of 720 pixels, thanks to the ever increasing pixel density. – user1938357 Sep 15 '13 at 14:26
  • 32
    @user1938357 note the "dp" in the "sw600dp", this means that this does not compare to real pixels but to density independent pixels. So although S3 has 720px, it still has way less then 600dp. – Sabo Dec 22 '13 at 11:37
  • @user1938357, so do you have any alternative, as your comment is more obvious nowadays! Actually i want to distinguish from S3 and a tablet, which is a tablet!!! (lol) – nmxprime Apr 23 '14 at 04:06
  • 8
    As @Sabo says, nothing to do with pixels. We are talking with dp. You can see this like available space to display things. A tablet has more available space than a phone. Independently of the resolution. A sw600dp device has at least 600dp (7" screen). A sw720dp has at least 720dp (10" screens). A phone, like a Nexus S has a smallest width of 320dp and a Nexus 4, a sw384 and a GS5 will have bearly the same (sw360). So this technique works also with modern full HD phones. – ol_v_er Apr 23 '14 at 07:01
  • How do you differentiate for launch? There's only 1 AndroidManifest.xml file, isn't there? – Guy Kogus Jul 07 '14 at 12:42
  • @GuyKogus this works if you want to use the **same** `Activity` for phones and tablets. If you want to start different `Activity` for phones and tablets, have a look to the Google IO source code (https://github.com/google/iosched) they activate/deactivate the components at run-time with a "ConfigActivity". Like this they can use easily one `Activity` or an other with the sames `Intent`. – ol_v_er Jul 10 '14 at 08:14
  • 2
    Note: it's very important to include the isTablet value in the standard value file. If you don't include this you will get a ResourceNotFoundException when `boolean tabletSize = getResources().getBoolean(R.bool.isTablet);` is executed. – w3bshark Aug 15 '15 at 16:32
  • When you try upload apk in google play, you'll have more errors good luck :D –  Oct 16 '15 at 14:02
  • the dp-based solutions (layout-sw600dp etc) are getting useless as long as new smartphones have more dpis than most tablets in the market. For example, a Samsung Galaxy S4 or S5 will show the tablet layout, which is not the expected result. – voghDev Oct 21 '15 at 06:51
  • 2
    dpi and pixels are not the same. As @Sabo explains above, even if you have a 1920x1080 pixel phone as a S4 or S5, it their smallest width will not be 600dp. It will be 360dp (smallest width 1080px, it's in the xxhdpi x3 category. so 1080/3 = 360dp). So the sw600dp will work independently of the actual pixel resolution. – ol_v_er Oct 23 '15 at 07:19
  • @ol_v_er I need to test my application both on tablets and smartPhones. But some of my tablet's screen is <= samrtPhone's screen. Is there another solution for this? – Almett Nov 26 '15 at 03:41
  • @Alimjan is the size in centimeter of your tablets is less than your phones or is it in pixel? – ol_v_er Nov 30 '15 at 08:47
  • 1
    @ol_v_er is pixel.I need to do some test on tablet Nexus 7(720*1280) and smart phone NOKIA_X(RM-980) size of 1080*1920 .Any good solution for this? I think we should find out other different properties of tablet and smart phone. Thanks – Almett Nov 30 '15 at 11:38
  • The category has noting to do with actual pixels. See my comment above (Oct 23 at 7:19) – ol_v_er Nov 30 '15 at 14:46
  • 2
    This method is not working because if you start the app when you are in "landscape" mode in phones, d600p is passed so device think it is tablet. – Mert Serimer Jan 22 '16 at 13:49
  • 2
    @MertSerimer it works because I use **sw**600dp. It means the smallest width of both X and Y. So the orientation will have no impact. In the official documentation : "indicated by the shortest dimension of the available screen area" and "You can use this qualifier to ensure that, regardless of the screen's current orientation" http://developer.android.com/guide/practices/screens_support.html#NewQualifiers – ol_v_er Jan 22 '16 at 13:57
  • @ol_v_er I have used this approach but now this approach is failed because user can change phone small width to greater than 600dp from device developer option, so please tell me to handle that scenarion if user changed small width from settings. – Nand Feb 15 '17 at 13:12
  • there should be API call for android isTablet() and every manufacturer to hardcode this – Duna Feb 23 '17 at 09:06
  • @ol_v_er This is best answer. It is working fine till marshmallow. From Nougat, When I used multi-window `isTabletMode` get from `values` folder, not from `values-sw600dp` or `values-sw720dp`. – Ankita Shah Mar 31 '17 at 12:35
  • Untill android let smartphones bigger than 6" size 'Configuration.SCREENLAYOUT_SIZE_LARGE' was working perfect. However now this is best answer. – OMArikan Apr 19 '17 at 13:24
  • Not working for me... device is GT-P5113 – NehaK Feb 07 '18 at 06:22
  • It not always works. I use a Samsung tablet. When I use the largest screen zoo, this solution failed. I am thinking about other solution to cover this case. – Richard Dec 14 '20 at 05:50
  • @user2294911 Some tablets do not work as expected but have you double checked your implementation first? – ol_v_er Mar 26 '21 at 13:24
99

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
}
gtsouk
  • 5,208
  • 1
  • 28
  • 35
  • 1
    I am happy it was helpfull to you – gtsouk Aug 26 '14 at 11:36
  • 1
    That's the solution I use. Only thing is that threshold value should be a bit higher now (2015: big smartphones and also Phablet): I use 6.5 inches and above for Tablet. – Pascal May 28 '15 at 07:58
  • 1
    @Pascal Yes you are right. At the time of writing (a year ago) most phones where smaller than 5''. But now 6.5'' sounds more reasonable. I updated my answer. – gtsouk May 28 '15 at 14:39
  • 2
    Not working for me. I gives 4.89 for 10 inch Nexus 10 and 5.88 for 5 inch Galaxy S2. – Aawaz Gyawali Aug 10 '15 at 14:16
  • It really helps me, thanks. – Neo Jun 20 '16 at 07:05
  • I used your solution in my app, but it fails with Huawei P8max 6.8" phone. Do you think using diagonalInches>=7 will solve the problem? – HaiderSahib Jun 23 '19 at 23:23
  • This looks like a better answer now, I just had a case where a 10 inch tablet had a smallest width qualifier < 600dp... so sw600dp did not work – oziomajnr Aug 02 '19 at 11:30
  • hi, can i call this method without activity variable? – famfamfam Mar 09 '21 at 10:57
  • 1
    [Years later] IMHO, diagonal dimension is not as useful as smallest dimension, because there are now some very tall phone screens. Should not categorize these as tablets, because the ones I'm referring to are still quite narrow. – ToolmakerSteve Jul 22 '22 at 22:18
  • Yeah, tell that 6.5 inch thing to Pixel 7 Pro :) https://en.wikipedia.org/wiki/Pixel_7 – Gaket Mar 13 '23 at 23:10
41

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";
        }
  • 8
    Problem with this approach is that some telephony devices may have large screen – user210504 Oct 18 '12 at 19:54
  • 5
    Given the influx of phone-tabs, I used a combination of the two solutions. True = tablet, false = not `TelephonyManager manager = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE); /*if no telephony, it's a tablet. Otherwise, chack boolean file*/ boolean tablet = manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE || activity.getResources().getBoolean(R.bool.isTablet); ` – Randy Mar 12 '13 at 02:26
  • 8
    I just tried that with a Samsung Tab 7 and it returns `PHONE_TYPE_GSM`. I guess because of the SIM-card module init. So absolutely not reliable. – ohcibi Dec 17 '13 at 11:10
  • Did you test it on a phone (handset device) without a SIM card in it? – Khulja Sim Sim Apr 24 '14 at 19:44
  • 1
    Not future proof. Breaks as soon as someone makes a tablet that can make calls. – atreat Oct 10 '14 at 19:21
  • In nexus 4, Android 5. it returns false during the bootup. – kakopappa Apr 02 '15 at 07:23
32

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;
}
Community
  • 1
  • 1
Jason
  • 1,238
  • 1
  • 15
  • 18
  • Your isTablet solution is e.g. not working on a Emulator with API 18 and Nexus 7 1200 x 1920 xhdpi ! – Ingo Oct 13 '14 at 05:23
  • @Ingo Not sure what you mean by not working, but I just fired up a test project using Eclipse and Android Studio and it worked correctly for both on a Nexus 7 1200 x 1920: xhdpi AVD. Are you getting errors in the IDE? Does the app compile? Does isTablet return false? What values are returned for the SCREENLAYOUT sizes? How are you calling isTablet? You really don't have any info that allows someone to try to help you. If you're really stuck, you might try posting an actual question with code examples so it will be easier to help. – Jason Oct 18 '14 at 02:16
  • Yes "isTablet(Context context)" returns false. Did you use API 18? – Ingo Oct 20 '14 at 02:46
  • Yes, I used API 18, sorry I left that out. I had compileSDKVersion and targetSDKVersion set to 21 in Android studio and both set to 18 in Eclipse. I'd make sure those are both set to at least 18. minSDKVersion was set to 18 for both as well. I would suggest that you post a question with example code if you need additional help. – Jason Oct 21 '14 at 03:47
  • @Jason Thanks for the answer. Cheers mate! +1 – Redson Jul 23 '15 at 20:41
  • 1
    Doesn't work in Nexus 5 – SweetWisher ツ May 05 '16 at 08:49
  • This isTablet method does not work on Redmi Note 10 – Żabojad Oct 19 '22 at 07:21
14

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; 
}
Parampal Pooni
  • 2,958
  • 8
  • 34
  • 40
Jorgesys
  • 124,308
  • 23
  • 334
  • 268
  • This solution is e.g. not working on a Emulator with API 18 and Nexus 7 1200 x 1920 xhdpi ! – Ingo Oct 13 '14 at 05:22
  • Hey, one of my testing devices is a Nexus 7 and works perfect, Im wondering why isn[t working on your Emulator. >` – Jorgesys Oct 13 '14 at 14:43
  • I dont know what is wrong in your code. But I have tested on Emulator and the result of "isTablet(Context ctx) was false. Try by self on Emulator. – Ingo Oct 13 '14 at 15:59
  • It's decrepated. That's why. – António Paulo Mar 16 '16 at 15:13
  • Are you sure that this is deprecated? do you have info about it? import android.content.res.Configuration; I have targetSDK = 21 and it Works. – Jorgesys Mar 16 '16 at 15:16
  • it's not deprecated but not working right on smartphones are bigger than 6" – OMArikan Apr 19 '17 at 09:09
7

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 
    }
Nolf
  • 113
  • 1
  • 10
  • did you tested it with what promising values of `smallestTabletSize` – nmxprime Apr 23 '14 at 04:09
  • Nice answer. I extended it a bit, calculating the screen diagonal. Anything above 5inches i consider a tablet. Read my answer below. – gtsouk Jul 11 '14 at 15:21
  • The `if` test used here results in largest dimension being used to determine whether is tablet. This is not a good idea; phones can be quite tall yet too narrow to be treated as a tablet. Better to use smallest dimension: `if (Math.Min(xInches, yInches) > largestPhoneWidth) // is a "tablet"`. – ToolmakerSteve Jul 22 '22 at 22:25
5

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.

2

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.

Ivan Ferić
  • 4,725
  • 11
  • 37
  • 47
Stephan
  • 21
  • 1
1

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.

John Ulmer
  • 11
  • 2