Планшет или телефон - Android

Есть ли способ проверить, использует ли пользователь планшет или телефон? У меня проблемы с функцией наклона и моим новым планшетом (Transformer)

28 ответов

Как уже упоминалось ранее, вы не хотите проверять, является ли устройство планшетом или телефоном, но вы хотите знать о функциях устройства,

В большинстве случаев разница между планшетом и телефоном заключается в размере экрана, поэтому вы хотите использовать разные файлы макетов. Эти файлы хранятся в res/layout-<qualifiers> каталоги. Вы можете создать файл XML в Directoy res/values-<same qualifiers> для каждого из ваших макетов и поместите в него ресурс int/bool/string, чтобы различать используемые вами макеты.

Пример:

файл res/values/screen.xml (при условии, res/layout/ содержит ваши файлы макетов для телефонов)

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


файл res/values-sw600dp/screen.xml (при условии, res/layout-sw600dp/ содержит файлы макетов для небольших планшетов, таких как Nexus 7)

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


файл res/values-sw720dp/screen.xml (при условии, res/layout-sw720dp/ содержит файлы макетов для больших планшетов, таких как Nexus 10):

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


Теперь тип экрана доступен через R.string.screen_type постоянная.

Чтобы определить, является ли устройство планшетом, используйте следующий код:

public boolean isTablet(Context context) {
    boolean xlarge = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);
    boolean large = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE);
    return (xlarge || large);
}

Размеры экрана LARGE и XLARGE определяются производителем в зависимости от расстояния до глаза, на котором они будут использоваться (таким образом, идея планшета).

Дополнительная информация: http://groups.google.com/group/android-developers/browse_thread/thread/d6323d81f226f93f

Этот пост мне очень помог,

К сожалению, у меня нет репутации, необходимой для оценки всех ответов, которые мне помогли.

Мне нужно было определить, было ли мое устройство планшетом или телефоном, и тогда я смог бы реализовать логику экрана. И в моем анализе планшет должен быть больше 7 дюймов (Xlarge), начиная с MDPI.

Вот код ниже, который был создан на основе этого поста.

/**
 * Checks if the device is a tablet or a phone
 * 
 * @param activityContext
 *            The Activity Context.
 * @return Returns true if the device is a Tablet
 */
public static boolean isTabletDevice(Context activityContext) {
    // Verifies if the Generalized Size of the device is XLARGE to be
    // considered a Tablet
    boolean xlarge = ((activityContext.getResources().getConfiguration().screenLayout & 
                        Configuration.SCREENLAYOUT_SIZE_MASK) == 
                        Configuration.SCREENLAYOUT_SIZE_XLARGE);

    // If XLarge, checks if the Generalized Density is at least MDPI
    // (160dpi)
    if (xlarge) {
        DisplayMetrics metrics = new DisplayMetrics();
        Activity activity = (Activity) activityContext;
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

        // MDPI=160, DEFAULT=160, DENSITY_HIGH=240, DENSITY_MEDIUM=160,
        // DENSITY_TV=213, DENSITY_XHIGH=320
        if (metrics.densityDpi == DisplayMetrics.DENSITY_DEFAULT
                || metrics.densityDpi == DisplayMetrics.DENSITY_HIGH
                || metrics.densityDpi == DisplayMetrics.DENSITY_MEDIUM
                || metrics.densityDpi == DisplayMetrics.DENSITY_TV
                || metrics.densityDpi == DisplayMetrics.DENSITY_XHIGH) {

            // Yes, this is a tablet!
            return true;
        }
    }

    // No, this is not a tablet!
    return false;
}

Почему бы не рассчитать размер диагонали экрана и не использовать ее, чтобы принять решение, является ли устройство телефоном или планшетом?

private boolean isTablet()
{
    Display display = getWindowManager().getDefaultDisplay();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    display.getMetrics(displayMetrics);

    int width = displayMetrics.widthPixels / displayMetrics.densityDpi;
    int height = displayMetrics.heightPixels / displayMetrics.densityDpi;

    double screenDiagonal = Math.sqrt( width * width + height * height );
    return (screenDiagonal >= 9.0 );
}

Конечно, можно утверждать, должен ли порог быть 9 дюймов или меньше.

Нет никакой разницы. Вы должны определить, что, по вашему мнению, является разницей, и проверить это. Галактика - это телефон? или планшет? и почему?

Вы должны определить, какие конкретные функции вы ищете, и код для этого.

Кажется, вы ищете "наклон". Я думаю, что это то же самое, что акселерометр (это слово?). Вы можете просто проверить, поддерживает ли устройство это, используя:

public class Accel extends Activity implements SensorListener {
...
  SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
  boolean accelSupported = sensorMgr.registerListener(this,
        SENSOR_ACCELEROMETER,
        SENSOR_DELAY_UI);
...
}

http://stuffthathappens.com/blog/2009/03/15/android-accelerometer/. Я не проверял это)

Я предполагаю, что когда вы определяете "Мобильный телефон", вы хотите знать, можете ли вы сделать телефонный звонок на устройстве, что нельзя сделать на чем-то, что будет определено как "планшет". Способ проверить это ниже. Если вы хотите узнать что-то по сенсорам, размеру экрана и т. Д., То это действительно другой вопрос.

Кроме того, при использовании разрешения экрана или больших ресурсов управления ресурсами против xlarge, возможно, было правильным подходом в прошлом. Новые мобильные устройства теперь выпускаются с такими большими экранами и высоким разрешением, что они размывают эту линию, хотя, если вы действительно хотите чтобы узнать телефонный звонок против возможности телефонного звонка, ниже "лучше".

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

В исходном коде приложения Google IOSched 2017 используется следующий метод:

public static boolean isTablet(Context context) {
    return context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
}

Основанный на Роберте Дэйле Джонсоне III и Хелтоне Исаке, я придумал этот код.

public static boolean isTablet(Context context) {
    TelephonyManager manager = 
        (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    if (manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) {
        //Tablet
        return true;
    } else {
        //Mobile
        return false; 
    }
}

public static boolean isTabletDevice(Context activityContext) {
    // Verifies if the Generalized Size of the device is XLARGE to be
    // considered a Tablet
    boolean xlarge = 
         ((activityContext.getResources().getConfiguration().screenLayout & 
           Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);

    // If XLarge, checks if the Generalized Density is at least MDPI (160dpi)
    if (xlarge) {
        DisplayMetrics metrics = new DisplayMetrics();
        Activity activity = (Activity) activityContext;
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

        // MDPI=160, DEFAULT=160, DENSITY_HIGH=240, DENSITY_MEDIUM=160,
        // DENSITY_TV=213, DENSITY_XHIGH=320
        if (metrics.densityDpi == DisplayMetrics.DENSITY_DEFAULT
                  || metrics.densityDpi == DisplayMetrics.DENSITY_HIGH
                  || metrics.densityDpi == DisplayMetrics.DENSITY_MEDIUM   
                  || metrics.densityDpi == DisplayMetrics.DENSITY_XHIGH) {

             // Yes, this is a tablet!
             return true;
        }
    }

    // No, this is not a tablet!
    return false;
}

Так что в вашем коде сделать фильтр как

if(isTabletDevice(Utilities.this) && isTablet(Utilities.this)){
    //Tablet
} else {
    //Phone
}

Код не нужен

Другие ответы перечисляют множество способов программного определения, является ли устройство телефоном или планшетом. Однако, если вы читаете документацию, это не рекомендуемый способ поддержки экранов различных размеров.

Вместо этого объявите различные ресурсы для планшетов или телефонов. Вы делаете это, добавляя дополнительные папки ресурсов для layout, values, так далее.

  • Для Android 3.2 (уровень API 13), добавьте sw600dp папка. Это означает, что минимальная ширина составляет не менее 600dp, что примерно равно разнице между телефоном и планшетом. Тем не менее, вы также можете добавить другие размеры. Посмотрите этот ответ, чтобы узнать, как добавить дополнительный файл ресурсов макета.

  • Если вы также поддерживаете устройства до Android 3.2, то вам нужно будет добавить large или же xlarge папки для поддержки планшетов. (Телефоны, как правило, small а также normal.)

Вот изображение того, что может понравиться вашим ресурсам после добавления дополнительных XML-файлов для экранов разных размеров.

При использовании этого метода система определяет все за вас. Вам не нужно беспокоиться о том, какое устройство используется во время выполнения. Вы просто предоставляете соответствующие ресурсы и позволяете Android делать всю работу.

Заметки

  • Вы можете использовать псевдонимы, чтобы избежать дублирования идентичных файлов ресурсов.

Документы Android стоит прочитать

Для тех, кто хочет обратиться к коду Google, решение о том, какие устройства будут использовать пользовательский интерфейс планшета, см. Ниже:

  // SystemUI (status bar) layout policy
        int shortSizeDp = shortSize
                * DisplayMetrics.DENSITY_DEFAULT
                / DisplayMetrics.DENSITY_DEVICE;

        if (shortSizeDp < 600) {
            // 0-599dp: "phone" UI with a separate status & navigation bar
            mHasSystemNavBar = false;
            mNavigationBarCanMove = true;
        } else if (shortSizeDp < 720) {
            // 600-719dp: "phone" UI with modifications for larger screens
            mHasSystemNavBar = false;
            mNavigationBarCanMove = false;
        } else {
            // 720dp: "tablet" UI with a single combined status & navigation bar
            mHasSystemNavBar = true;
            mNavigationBarCanMove = false;
        }
        }

Этот метод является рекомендацией Google. Я вижу этот код в приложении Google Offical для Android iosched

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

Если определение размера экрана не возвращает правильное значение на новых устройствах, попробуйте:

/*
 Returns '1' if device is a tablet
 or '0' if device is not a tablet.
 Returns '-1' if an error occured.
 May require READ_EXTERNAL_STORAGE
 permission.
 */
public static int isTablet()
{
    try
    {
        InputStream ism = Runtime.getRuntime().exec("getprop ro.build.characteristics").getInputStream();
        byte[] bts = new byte[1024];
        ism.read(bts);
        ism.close();

        boolean isTablet = new String(bts).toLowerCase().contains("tablet");
        return isTablet ? 1 : 0;
    }
    catch (Throwable t)
    {t.printStackTrace(); return -1;}
}

Проверено на Android 4.2.2 (извините за мой английский.)

Если вы ориентируетесь только на уровень API>= 13, попробуйте

public static boolean isTablet(Context context) {
    return context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
}

ура:-)

Что ж, лучшее решение, которое сработало для меня, довольно простое:

private boolean isTabletDevice(Resources resources) {   
    int screenLayout = resources.getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
    boolean isScreenLarge = (screenLayout == Configuration.SCREENLAYOUT_SIZE_LARGE);
    boolean isScreenXlarge = (screenLayout == Configuration.SCREENLAYOUT_SIZE_XLARGE);
    return (isScreenLarge || isScreenXlarge);
}

Используется так:

public void onCreate(Bundle savedInstanceState) {
    [...]
    if (this.isTabletDevice(this.getResources()) == true) {
        [...]
    }
}

Я действительно не хочу смотреть на размеры пикселей, а полагаюсь только на размер экрана.

Работает хорошо, так как Nexus 7 (LARGE) определяется как планшет, но не Galaxy S3 (NORMAL).

Используйте этот метод, который возвращает истину, когда устройство является планшетом

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

Думая о "новых" зарезервированных каталогах (например, values-sw600dp), я создал этот метод на основе ширины экрана DP:

 public static final int TABLET_MIN_DP_WEIGHT = 450;
 protected static boolean isSmartphoneOrTablet(Activity act){
    DisplayMetrics metrics = new DisplayMetrics();
    act.getWindowManager().getDefaultDisplay().getMetrics(metrics);

    int dpi = 0;
    if (metrics.widthPixels < metrics.heightPixels){
        dpi = (int) (metrics.widthPixels / metrics.density);
    }
    else{
        dpi = (int) (metrics.heightPixels / metrics.density);
    }

    if (dpi < TABLET_MIN_DP_WEIGHT)         return true;
    else                                    return false;
}

И в этом списке вы можете найти некоторые DP популярных устройств и размеров планшетов:

Wdp / Hdp

ГАЛАКТИКА Нексус: 360/567
XOOM: 1280/752
ГАЛАКТИКА ПРИМЕЧАНИЕ: 400 / 615
НЕКСУС 7: 961/528
GALAXY TAB (> 7 && <10): 1280/752
GALAXY S3: 360/615

Wdp = ширина дп
Hdp = высота дп

public boolean isTablet() {
        int screenLayout = getResources().getConfiguration().screenLayout;
        return (Build.VERSION.SDK_INT >= 11 &&
                (((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) || 
                 ((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE)));
    }

Приведенный ниже метод рассчитывает длину диагонали экрана устройства, чтобы определить, является ли устройство телефоном или планшетом. Единственная проблема, связанная с этим методом, заключается в том, какое пороговое значение определяет, будет устройство планшетным или нет. в приведенном ниже примере я установил его как 7 дюймов и выше.

public static boolean isTablet(Activity act)
{
    Display display = act.getWindow().getWindowManager().getDefaultDisplay();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    display.getMetrics(displayMetrics);

    float width = displayMetrics.widthPixels / displayMetrics.xdpi;
    float height = displayMetrics.heightPixels / displayMetrics.ydpi;

    double screenDiagonal = Math.sqrt( width * width + height * height );
    int inch = (int) (screenDiagonal + 0.5);
    Toast.makeText(act, "inch : "+ inch, Toast.LENGTH_LONG).show();
    return (inch >= 7 );
}

com.sec.feature.multiwindow.tablet в диспетчере пакетов относится только к планшету, а com.sec.feature.multiwindow.phone - к телефону.

Я знаю, что это не прямой ответ на ваш вопрос, но другие ответы здесь дают хорошее представление о том, как определить размер экрана. Вы написали в своем вопросе, что у вас есть проблемы с наклоном, и это также случилось со мной.

Если вы запускаете гироскоп (или датчик вращения) на смартфоне, оси x и y могут быть определены иначе, чем на планшете, в соответствии с ориентацией этого устройства по умолчанию (например, Samsung GS2 - портрет по умолчанию, Samsung GT-7310 - пейзаж по умолчанию, новый Google Nexus 7 - портрет по умолчанию, хотя это планшет!).

Теперь, если вы хотите использовать Gyroscope, вы можете получить работающее решение для смартфонов, но с ошибками на некоторых планшетах или наоборот.

Если вы используете одно из приведенных выше решений, выберите размер экрана, а затем примените

SensorManager.remapCoordinateSystem(inputRotationMatrix, SensorManager.AXIS_X, 
    SensorManager.AXIS_Y, outputRotationMatrix);

перевернуть ось, если она имеет большой или большой размер экрана, это может сработать в 90% случаев, но, например, на Nexus 7 это вызовет проблемы (поскольку у него книжная ориентация по умолчанию и большой размер экрана).

Простейший способ исправить это предоставляется в образце RotationVectorSample, который поставляется с демонстрационными примерами API, установив sceenOrientation в значение nosensor в вашем манифесте:

<activity
    ...
    android:screenOrientation="nosensor">
...
</activity>

Смартфон / планшет мне нужно было обнаружить только в файле макета, потому что я использую код навигации.

Сначала я создал каталог layout-sw600dp, но он не работал должным образом, потому что он активировался на моем Nokia 8 в ландшафтном режиме, но высота экрана была бы слишком маленькой.

Итак, я переименовал каталог в layout-sw600dp-h400dp и добился желаемого эффекта. Параметр h-xxxdp должен зависеть от того, сколько контента вы хотите поместить в свой макет, и, как таковой, должен зависеть от приложения.

Становится все труднее проводить черту между телефоном и планшетом. Например, (по состоянию на август 2015 года) устройство Samsung Mega 6.3 извлекает ресурсы из папок sw600dp - что касается Android, то это планшет.

Ответ от @Vyshnavi работает на всех протестированных нами устройствах, но не на Mega 6.3.

Ответ @Helton Isac, приведенный выше, возвращает Mega 6.3 в качестве телефона, но поскольку устройство по-прежнему захватывает ресурсы из sw600dp, это может вызвать другие проблемы - например, если вы используете пейджер для телефонов, а не для планшетов, вы столкнетесь с ошибками NPE,

В конце концов, кажется, что есть слишком много условий для проверки, и нам, возможно, придется признать, что некоторые телефоны на самом деле являются планшетами:-P

Это метод, который я использую:

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

С помощью:

Конфигурация. SCREENLAYOUT_SIZE_MASK

Конфигурация. SCREENLAYOUT_SIZE_LARGE

Это рекомендуемый метод!

Зачем использовать это?

Use this method which returns true when the device is a tablet

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

я вижу много способов выше. Класс Configuration получил правильный ответ чуть ниже:

    /**
 * Check if the Configuration's current {@link #screenLayout} is at
 * least the given size.
 *
 * @param size The desired size, either {@link #SCREENLAYOUT_SIZE_SMALL},
 * {@link #SCREENLAYOUT_SIZE_NORMAL}, {@link #SCREENLAYOUT_SIZE_LARGE}, or
 * {@link #SCREENLAYOUT_SIZE_XLARGE}.
 * @return Returns true if the current screen layout size is at least
 * the given size.
 */
public boolean isLayoutSizeAtLeast(int size) {
    int cur = screenLayout&SCREENLAYOUT_SIZE_MASK;
    if (cur == SCREENLAYOUT_SIZE_UNDEFINED) return false;
    return cur >= size;
}

просто позвони:

 getResources().getConfiguration().
 isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);

все нормально?

Я думаю, что планшет имеет минимальную и максимальную ширину и высоту 600 пикселей,
поэтому нужно знать плотность экрана и высоту / ширину в дп,
чтобы получить значение:

DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth(); 
int height = display.getHeight(); 
float density = metrics.density;  
if((width/density>=600 && height/density>=600))
 isTablette = true;
else
 isTablette = false;

Я рекомендую Android-библиотеку "кофеин", которая содержит телефон или планшет, и 10 дюймов ~!

очень прост в использовании.

библиотека здесь.

https://github.com/ShakeJ/Android-Caffeine-library

и использовать

DisplayUtil.isTablet(this);
DisplayUtil.isTenInch(this);

Для меня различие между телефоном и планшетом - не размер устройства и / или плотность пикселей, которые будут меняться в зависимости от технологии и вкуса, а скорее соотношение размеров экрана. Если я показываю экран с текстом, мне нужно знать, нужно ли, скажем, 15 длинных строк (телефон) против 20 более коротких строк (планшет). Для моей игры я использую следующее для приблизительной оценки прямоугольника, с которым будет работать мое программное обеспечение:

    Rect surfaceRect = getHolder().getSurfaceFrame();
    screenWidth = surfaceRect.width();
    screenHeight = surfaceRect.height();
    screenWidthF = (float) screenWidth;
    screenHeightF = (float) screenHeight;
    widthheightratio = screenWidthF/screenHeightF;
    if(widthheightratio>=1.5) {
        isTablet=false;
    }else {
        isTablet=true;
    }

Например, есть одно важное отличие (по крайней мере, для моей программы) между телефоном и планшетом. Это ориентация устройства по умолчанию. Телефон имеет портретную ориентацию, планшет - альбомную. И соответственно метод определения устройства:

private static boolean isLandscapeDefault(Display display) {
    Log.d(TAG, "isTablet()");
    final int width = display.getWidth();
    final int height = display.getHeight();

    switch (display.getOrientation()) {
    case 0: case 2:
        if(width > height) return true;
        break;
    case 1: case 3:
        if(width < height) return true;
        break;
    }
    return false;
}

ИЗДАНО: После обсуждения с Дэном Халмом изменилось название метода.

Пожалуйста, проверьте ниже код.

private boolean isTabletDevice() {
  if (android.os.Build.VERSION.SDK_INT >= 11) { // honeycomb
    // test screen size, use reflection because isLayoutSizeAtLeast is
    // only available since 11
    Configuration con = getResources().getConfiguration();
    try {
      Method mIsLayoutSizeAtLeast = con.getClass().getMethod(
      "isLayoutSizeAtLeast", int.class);
      boolean r = (Boolean) mIsLayoutSizeAtLeast.invoke(con,
      0x00000004); // Configuration.SCREENLAYOUT_SIZE_XLARGE
      return r;
    } catch (Exception x) {
      x.printStackTrace();
      return false;
    }
  }
  return false;
}

Я думаю, что это самый простой способ быть честным. Это проверит размер используемого экрана:

Display display = getWindowManager().getDefaultDisplay(); 
int width = display.getWidth();
int height = display.getHeight();

Удачи!

Другие вопросы по тегам