it-swarm.com.ru

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

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

136
Benny

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

В большинстве случаев разница между планшетом и телефоном заключается в размере экрана, поэтому вы хотите использовать разные файлы макетов. Эти файлы хранятся в каталогах res/layout-<qualifiers>. Вы можете создать XML-файл в директории 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.

115
John

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

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

59
petey

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

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

Мне нужно было определить, было ли мое устройство планшетом или телефоном, и тогда я смог бы реализовать логику экрана. И в моем анализе планшет должен быть больше 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;
}
38
Helton Isac

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

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 дюймов или меньше.

13
Volker Voecking

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

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

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

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/ . Я не проверял это)

11
Nanne

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

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

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

Основываясь на Роберте Дейле Джонсоне 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
}
6
Cjames

Для тех, кто хочет обратиться к коду 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;
        }
        }
3
Pier Betos

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

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

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

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

ура :-)

2
dheeran

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

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

Код не нужен

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

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

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

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

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

 enter image description here

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

Заметки

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

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

2
Suragch

Думая о «новых» зарезервированных каталогах (например, 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
NEXUS 7: 961/528
GALAXY TAB (> 7 && <10): 1280/752
GALAXY S3: 360/615 

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

1
Aracem

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

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

1
Max

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

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

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

/*
 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 (извините за мой английский.)

1
BSTech
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)));
    }
0
Xar E Ahmer

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

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

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

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

0
bkurzius

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

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

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

0
alei long

приведенный ниже метод рассчитывает длину диагонали экрана устройства, чтобы определить, является ли устройство телефоном или планшетом. Единственная проблема, связанная с этим методом, заключается в том, какое пороговое значение определяет, будет ли устройство планшетным или нет. в примере ниже я установил его как 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 );
}
0
MinFu

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

0
RBz

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

Если вы запускаете гироскоп (или датчик вращения) на смартфоне, то оси 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>
0
Alexander Pacha

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

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

С помощью:

Configuration. SCREENLAYOUT_SIZE_MASK

Configuration. SCREENLAYOUT_SIZE_LARGE

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

0
Elenasys