web-dev-qa-db-fra.com

Tablette ou téléphone - Android

Existe-t-il un moyen de vérifier si l’utilisateur utilise une tablette ou un téléphone?

136
Benny

Comme il a été mentionné précédemment, vous ne souhaitez pas vérifier si le périphérique est une tablette ou un téléphone, mais vous souhaitez en savoir plus sur les fonctionnalités du périphérique,

La plupart du temps, la différence entre une tablette et un téléphone réside dans la taille de l'écran, raison pour laquelle vous souhaitez utiliser des fichiers de présentation différents. Ces fichiers sont stockés dans les répertoires res/layout-<qualifiers>. Vous pouvez créer un fichier XML dans directoy res/values-<same qualifiers> pour chacune de vos présentations et y insérer une ressource int/bool/string afin de distinguer les présentations que vous utilisez.

Exemple:

Fichier res/values/screen.xml (en supposant que res/layout/ contient vos fichiers de présentation pour les combinés)

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


Fichier res/values-sw600dp/screen.xml (en supposant que res/layout-sw600dp/ contient vos fichiers de mise en page pour les petites tablettes comme le Nexus 7) 

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


Fichier res/values-sw720dp/screen.xml (en supposant que res/layout-sw720dp/ contient vos fichiers de mise en page pour les grandes tablettes comme le Nexus 10): 

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


Maintenant, le type d'écran est accessible via la constante R.string.screen_type.

115
John

Pour détecter si le périphérique est une tablette, utilisez le code suivant:

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

Les tailles d'écran GRAND et XLARGE sont déterminées par le fabricant en fonction de la distance qui les sépare de l'œil (d'où l'idée d'une tablette). 

Plus d'infos: http://groups.google.com/group/Android-developers/browse_thread/thread/d6323d81f226f93f

59
petey

Ce post m'a beaucoup aidé,

Malheureusement, je n'ai pas la réputation nécessaire pour évaluer toutes les réponses qui m'ont aidé.

J'avais besoin d'identifier si mon appareil était une tablette ou un téléphone, ce qui me permettrait de mettre en œuvre la logique de l'écran. Et dans mon analyse, la tablette doit mesurer plus de 7 pouces (Xlarge) à partir de MDPI.

Voici le code ci-dessous, créé à partir de ce post.

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

Pourquoi ne pas calculer la taille de la diagonale de l’écran et l’utiliser pour décider si l’appareil est un téléphone ou une tablette?

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

Bien sûr, on peut se demander si le seuil devrait être de 9 pouces ou moins.

13
Volker Voecking

il n'y a pas de différence. Vous devriez définir ce que vous pensez être la différence et vérifier cela. Une galaxie est-elle un téléphone? ou une tablette? et pourquoi?

Vous devez définir les fonctionnalités spécifiques que vous recherchez et coder pour cela.

Il semble que vous recherchiez «inclinaison». Je pense que c'est la même chose que l'accéléromètre (est-ce un mot?). Vous pouvez simplement vérifier si l'appareil le prend en charge, en utilisant:

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

(de http://stuffthathappens.com/blog/2009/03/15/Android-accelerometer/ . Je ne l'ai pas testé)

11
Nanne

Mon hypothèse est que, lorsque vous définissez «Mobile/Phone», vous souhaitez savoir si vous pouvez effectuer un appel téléphonique sur l'appareil, ce qui ne peut pas être fait sur quelque chose qui serait défini comme une «tablette». La façon de vérifier ceci est ci-dessous. Si vous souhaitez savoir quelque chose en fonction de capteurs, de la taille de l’écran, etc., la question est vraiment différente. 

En outre, l'utilisation de la résolution d'écran ou de la gestion des ressources large vs xlarge peut s'avérer une approche valable dans le passé. De nouveaux appareils «mobiles» arrivent maintenant avec des écrans si grands et des résolutions aussi élevées qu'ils brouillent cette ligne alors pour connaître les appels téléphoniques par rapport aux appels sans appels téléphoniques, le meilleur choix est indiqué ci-dessous.

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

Basé sur Robert Dale Johnson III et Helton Isac, je suis arrivé avec ce code. J'espère que cela sera utile. 

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

Donc, dans votre code, faites un filtre comme

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

Pour ceux qui veulent se référer au code de Google pour décider quels appareils utiliseront une interface utilisateur pour tablette, vous pouvez vous référer à:

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

Cette méthode est une recommandation de Google. Je vois ce code dans Google Android App Android iosched

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

Si vous ne ciblez que le niveau API> = 13, essayez

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

à votre santé :-)

2
dheeran

Dans l'application Google IOSched 2017 code source , la méthode suivante est utilisée:

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

Aucun code requis

Les autres réponses énumèrent de nombreuses façons de déterminer par programme si le périphérique est un téléphone ou une tablette. Cependant, si vous lisez documentation , ce n’est pas la méthode recommandée pour prendre en charge diverses tailles d’écran.

Déclarez plutôt des ressources différentes pour les tablettes ou les téléphones. Vous faites cela en ajoutant des dossiers de ressources supplémentaires pour layout, values, etc.

  • Sous Android 3.2 (niveau 13 de l'API), ajoutez un dossier sw600dp. Cela signifie que le s Mallest w idth est au moins 600dp, ce qui correspond approximativement à la division téléphone/tablette. Cependant, vous pouvez également ajouter d'autres tailles. Consultez cette réponse pour obtenir un exemple montrant comment ajouter un fichier de ressources de présentation supplémentaire. 

  • Si vous prenez également en charge les appareils antérieurs à Android 3.2, vous devrez ajouter des dossiers large ou xlarge pour prendre en charge les tablettes. (Les téléphones sont généralement small et normal.)

Voici une image de vos ressources après l’ajout de fichiers xml supplémentaires pour différentes tailles d’écran.

 enter image description here

Lorsque vous utilisez cette méthode, le système détermine tout pour vous. Vous n'avez pas à vous soucier du périphérique utilisé au moment de l'exécution. Vous fournissez simplement les ressources appropriées et laissez Android faire tout le travail. 

Remarques

  • Vous pouvez utiliser aliases pour éviter de dupliquer des fichiers de ressources identiques.

Android docs mérite d'être lu

2
Suragch

En pensant aux "nouveaux" répertoires acceptés (values-sw600dp par exemple), j'ai créé cette méthode sur la base de la largeur d'écran 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;
}

Et sur cette liste, vous trouverez quelques-uns des DP des appareils et des formats de tablette courants:

Wdp/Hdp

GALAXY Nexus: 360/567
XOOM: 1280/752
NOTE DE GALAXIE: 400/615
NEXUS 7: 961/528
GALAXY TAB (> 7 && <10): 1280/752
GALAXY S3: 360/615 

Wdp = Largeur dp
Hdp = Hauteur dp

1
Aracem

Eh bien, la meilleure solution qui a fonctionné pour moi est assez simple:

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

Utilisé comme ceci:

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

Je ne veux vraiment pas regarder les tailles en pixels mais me fier uniquement à la taille de l'écran.

Fonctionne bien car Nexus 7 (LARGE) est détecté sous forme de tablette, mais pas de Galaxy S3 (NORMAL).

1
Max

Utilisez cette méthode qui renvoie true lorsque l'appareil est une tablette.

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

Si la détection de la taille de l'écran ne renvoie pas une valeur correcte sur les nouveaux appareils, essayez:

/*
 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;}
}

Testé sur Android 4.2.2 (désolé pour mon anglais.)

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

Il devient de plus en plus difficile de faire la distinction entre téléphone et tablette. Par exemple (à partir d'août 2015), le Samsung Mega 6.3 appareil tire des ressources des dossiers sw600dp - en ce qui concerne Android, il s'agit d'une tablette. 

La réponse de @Vyshnavi fonctionne dans tous les appareils que nous avons testés, mais pas pour Mega 6.3. 

@Helton Isac answer ci-dessus renvoie le Mega 6.3 au format téléphone. Toutefois, étant donné que le périphérique récupère toujours les ressources de sw600dp, il peut entraîner d'autres problèmes, par exemple, si vous utilisez un viewpager pour les téléphones et non pour les tablettes, avec des erreurs NPE. 

En fin de compte, il semble qu'il y ait trop de conditions à vérifier et il se peut que nous devions simplement accepter que certains téléphones sont en fait des tablettes :-P

0
bkurzius

Je devais détecter le smartphone/la tablette uniquement dans le fichier de mise en page, car j'utilise le code de navigation.

Ce que j’avais fait en premier lieu, c’était de créer un répertoire layout-sw600dp, mais cela ne fonctionnait pas bien car il s’activerait sur mon Nokia 8 en mode paysage, mais la hauteur de l’écran serait trop petite.

J'ai donc renommé le répertoire en layout-sw600dp-h400dp puis j'ai obtenu l'effet souhaité. Le paramètre h-xxxdp doit dépendre de la quantité de contenu que vous souhaitez supprimer de votre mise en page et, en tant que tel, dépend de l'application.

0
Dominique Lorre

pourquoi utiliser ceci?

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

je vois plusieurs façons ci-dessus. La classe de configuration a la bonne réponse juste en dessous:

    /**
 * 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;
}

il suffit d'appeler :

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

c'est bon?

0
alei long

la méthode ci-dessous consiste à calculer la diagonale de l'écran de l'appareil pour déterminer si celui-ci est un téléphone ou une tablette. la seule préoccupation de cette méthode est de savoir quelle est la valeur seuil pour décider si le périphérique est comprimé ou non. dans l'exemple ci-dessous, je le fixe à 7 pouces et plus.

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 dans le gestionnaire de paquets est spécifique à tablet et com.sec.feature.multiwindow.phone est spécifique à phone.

0
RBz

Je sais que ce n'est pas directement une réponse à votre question, mais d'autres réponses ici donnent une bonne idée de la façon d'identifier la taille de l'écran. Vous avez écrit dans votre question que vous aviez des problèmes d'inclinaison et que cela m'est également arrivé.

Si vous utilisez le gyroscope (ou le capteur de rotation) sur un smartphone, les axes x et y peuvent être définis différemment de ceux d'une tablette. Selon l'orientation par défaut de cet appareil (par exemple, Samsung GS2 est le mode portrait par défaut, le Samsung GT-7310 est paysage par défaut, le nouveau Google Nexus 7 est un portrait par défaut, bien que ce soit une tablette!).

Maintenant, si vous voulez utiliser Gyroscope, vous pouvez vous retrouver avec une solution de travail pour les smartphones, mais une confusion des axes sur certaines tablettes ou l’inverse.

Si vous utilisez l’une des solutions ci-dessus pour choisir uniquement la taille d’écran, puis appliquez

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

pour retourner l’axe si la taille de l’écran est grande ou très grande, cela peut fonctionner dans 90% des cas, mais par exemple sur le Nexus 7, cela causera des problèmes (car il a une orientation portrait par défaut et une grande taille d’écran).

Le moyen le plus simple de résoudre ce problème est fourni dans RotationVectorSample fourni avec les démonstrations de l'API en définissant sceenOrientation sur nosensor dans votre manifeste:

<activity
    ...
    Android:screenOrientation="nosensor">
...
</activity>
0
Alexander Pacha

C'est la méthode que j'utilise:

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

En utilisant:

Configuration. SCREENLAYOUT_SIZE_MASK

Configuration. SCREENLAYOUT_SIZE_LARGE

C'est la méthode recommandée!

0
Elenasys