【问题标题】:Determine if the device is a smartphone or tablet? [duplicate]确定设备是智能手机还是平板电脑? [复制]
【发布时间】:2012-02-14 14:58:33
【问题描述】:

我想获取有关设备的信息,以查看它是智能手机还是平板电脑。我该怎么做?

我想根据设备类型从资源中显示不同的网页:

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 + ")";

但是,对我的情况来说似乎没用。


这个解决方案现在对我有用:

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)
}

【问题讨论】:

  • 使用 displaymetris 获取您的屏幕尺寸并执行此操作。
  • 找到屏幕尺寸是唯一的方法。您无法真正从“智能手机”和“平板电脑”的角度来考虑它。最后,屏幕尺寸是你想要的。
  • 您的差异仅基于布局吗?或者你打算给出完全不同的内容?多种布局和活动与片段是你的方式。
  • 使用物理像素是一个可怕的想法,因为设备的像素密度越来越高。至少你应该使用 dp 作为单位。

标签: android device-detection


【解决方案1】:

Android 培训中讨论了这个主题:

Use the Smallest-width Qualifier

如果您阅读了整个主题,它们会解释如何在特定值文件(如 res/values-sw600dp/attrs.xml)中设置布尔值:

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

因为 sw600dp 限定符仅对 android 3.2 以上的平台有效。如果您想确保此技术适用于所有平台(3.2 之前),请在 res/values-xlarge 文件夹中创建相同的文件:

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

然后,在“标准”值文件(如 res/values/attrs.xml)中,将布尔值设置为 false:

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

然后在您的活动中,您可以获取此值并检查您是否在平板电脑大小的设备中运行:

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

【讨论】:

  • 好答案!非常棒,但就我而言,我正在开发一个库,我无法将任何文件/目录更改/添加到项目中
  • 这个答案很好,但可能有点过时,因为现在不推荐使用 values-xlarge。使用 /res/values 和 /res/values-sw600 作为文件夹来存储这些值可能会更好解决方案。 sw600 表示“最小宽度 600”。如果屏幕最小维度的大小大于或等于 600dp,则选择该文件夹中的值。值和布局存储桶(文件夹)的一个很好的参考在这里:android-developers.blogspot.com/2012/07/…
  • 这可能不再有效,因为现在许多智能手机的最小宽度>600,例如三星 Galaxy s3,其最小宽度为 720 像素,这要归功于不断增加的像素密度。
  • @user1938357 注意“sw600dp”中的“dp”,这意味着这不是与真实像素相比,而是与密度无关像素。因此,虽然 S3 有 720px,但它仍然远低于 600dp。
  • 正如@Sabo 所说,与像素无关。我们正在与 dp 交谈。你可以看到这就像可用空间来展示东西。平板电脑比手机拥有更多可用空间。独立于分辨率。 sw600dp 设备至少有 600dp(7" 屏幕)。sw720dp 至少有 720dp(10" 屏幕)。 Nexus S 等手机的最小宽度为 320dp,而 Nexus 4、sw384 和 GS5 的宽度几乎相同(sw360)。所以这项技术也适用于现代全高清手机。
【解决方案2】:

我认为平板电脑至少有 6.5 英寸的屏幕。这是根据上面 Nolf 的回答计算它的方法。

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
}

【讨论】:

  • 很高兴对您有所帮助
  • 这就是我使用的解决方案。唯一的问题是现在阈值应该更高一些(2015 年:大型智能手机和平板手机):我使用 6.5 英寸及以上的平板电脑。
  • @Pascal 是的,你是对的。在撰写本文时(一年前),大多数手机都小于 5 英寸。但现在 6.5 英寸听起来更合理。我更新了我的答案。
  • 不适合我。我给 4.89 的 10 英寸 Nexus 10 和 5.88 的 5 英寸 Galaxy S2。
  • 这对我很有帮助,谢谢。
【解决方案3】:

我的假设是,当您定义“手机/电话”时,您想知道您是否可以在设备上拨打电话,而在被定义为“平板电脑”的设备上无法拨打电话。验证方法如下。如果您想了解基于传感器、屏幕尺寸等的信息,那么这确实是一个不同的问题。

此外,在使用屏幕分辨率或资源管理 large 与 xlarge 时,过去可能是一种有效的方法,新的“移动”设备现在配备了如此大的屏幕和高分辨率,以至于它们模糊了这条线,而如果您真的想知道电话与没有电话功能,以下是“最好的”。

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

【讨论】:

  • 这种方法的问题是某些电话设备可能有大屏幕
  • 鉴于电话标签的大量涌入,我使用了这两种解决方案的组合。真 = 平板电脑,假 = 不是 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);
  • 我刚刚用三星 Tab 7 尝试过,它返回 PHONE_TYPE_GSM。我猜是因为 SIM 卡模块初始化。所以绝对不可靠。
  • 你在没有SIM卡的手机(手机设备)上测试过吗?
  • 不是未来的证明。一旦有人制作出可以拨打电话的平板电脑,就会中断。
【解决方案4】:

我喜欢 Ol_v_er 的解决方案,它很简单,但是我发现它并不总是那么简单,新设备和显示器不断出现,我想更“细化”地尝试找出实际屏幕尺寸。我发现 John 的 here 的另一种解决方案使用字符串资源而不是布尔值来指定平板电脑的大小。因此,不要只将 true 放入 /res/values-sw600dp/screen.xml 文件(假设这是您的小型平板电脑的布局),您应该放入:

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

如下引用,然后根据结果做你需要的:

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

Sean O'Toole 对Detect 7 inch and 10 inch tablet programmatically 的回答也是我一直在寻找的。如果这里的答案不允许您像您希望的那样具体,您可能想检查一下。他很好地解释了如何计算不同的指标以弄清楚您实际处理的是什么。

更新

在查看 Google I/O 2013 应用程序源代码时,我遇到了他们用来识别设备是否是平板电脑的以下内容,所以我想我会添加它。以上为您提供了更多的“控制”,但如果您只想知道它是否是平板电脑,以下内容非常简单:

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

【讨论】:

  • 您的 isTablet 解决方案是例如不适用于具有 API 18 和 Nexus 7 1200 x 1920 xhdpi 的模拟器!
  • @Ingo 不知道你说的不工作是什么意思,但我刚刚使用 Eclipse 和 Android Studio 启动了一个测试项目,它在 Nexus 7 1200 x 1920 上都能正常工作:xhdpi AVD。您是否在 IDE 中遇到错误?应用程序是否编译? isTablet 返回 false 吗? SCREENLAYOUT 尺寸返回什么值?你怎么称呼isTablet?您真的没有任何信息可以让某人尝试帮助您。如果你真的被卡住了,你可以尝试发布一个带有代码示例的实际问题,这样会更容易提供帮助。
  • 是的 "isTablet(Context context)" 返回 false。你用过 API 18 吗?
  • 是的,我使用了 API 18,很抱歉我漏掉了。我在 Android Studio 中将 compileSDKVersion 和 targetSDKVersion 设置为 21,在 Eclipse 中都设置为 18。我会确保它们都设置为至少 18。minSDKVersion 也都设置为 18。如果您需要其他帮助,我建议您发布带有示例代码的问题。
  • 在 Nexus 5 中不起作用
【解决方案5】:

我在我所有的应用程序中都使用了这个方法,并且成功了:

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

【讨论】:

  • 这个解决方案是例如不适用于具有 API 18 和 Nexus 7 1200 x 1920 xhdpi 的模拟器!
  • 嘿,我的测试设备之一是 Nexus 7 并且运行良好,我想知道为什么您的模拟器无法运行。 >`
  • 我不知道你的代码有什么问题。但是我在模拟器上测试过,“isTablet(Context ctx) 的结果是假的。在模拟器上自己试试。
  • 它已经过时了。这就是为什么。
  • 您确定这已被弃用吗?你有这方面的信息吗?导入android.content.res.Configuration;我有 targetSDK = 21 并且它有效。
【解决方案6】:

由于平板电脑通常比智能手机大,并且由于低分辨率平板电脑的像素数可能与高分辨率智能手机相同,解决此问题的一种方法是计算设备的物理尺寸(而非分辨率):

    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 
    }

【讨论】:

  • 你用smallestTabletSize的有希望值测试了它
  • 不错的答案。我扩展了一点,计算屏幕对角线。任何超过 5 英寸的东西我都认为是平板电脑。在下面阅读我的答案。
【解决方案7】:

我发现的最好的、干扰性更小的选项是在你的 xml 中设置一个标签参数,比如

电话 XML 布局

<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"/>

平板电脑 XML 布局

<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>

然后在你的活动类中调用它:

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

希望它对你有用。

【讨论】:

    【解决方案8】:

    我使用的解决方案是定义两个布局。一个布局文件夹设置为例如 布局-sw600dp 我用它来为我的平板电脑用户提供一个菜单按钮,并为手机用户隐藏它。这样我就不必(还)为我现有的应用程序实现 ActionBar ...

    this post for more details

    【讨论】:

      【解决方案9】:

      Re:上面关于如何区分电话和非电话的切线:据我所知,只有电话具有 15 位 IMEI(国际移动站设备标识),因此以下代码将明确区分来自非电话的电话:

          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.");
          }
      

      我发现在 Nook 模拟器上 getPhoneType() 出于某种原因返回“GSM”的 phoneType,因此检查电话类型似乎是不可靠的。同样,getNetworkType() 将为处于飞行模式的手机返回 0。事实上,飞行模式也会导致 getLine1Number() 和 getSim* 方法返回 null。但即使在飞行模式下,手机的 IMEI 仍然存在。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-28
        • 2016-11-09
        • 2018-09-04
        • 1970-01-01
        • 1970-01-01
        • 2012-07-05
        • 1970-01-01
        • 2012-07-06
        相关资源
        最近更新 更多