使用非本机工具在 Qt 中检测平板电脑或手机的正确方法

A proper way to detect Tablet or Mobile in Qt using non-native tools

我的目的是确定我在其上部署应用程序的是平板电脑还是移动设备。

当我部署 iOS、Android、Linux 桌面和 Windows 应用程序时,最好使用非本机工具。

但作为实验的一部分,我为 android 尝试了以下技巧(java class 的方法):

实验#1

public class JniUtilities {
    public static boolean isTablet(Context context) {
        Log.d("INDENTIFICATOR >> ", "HEJJ, I AM CALLED!");
        return ((context.getResources().getConfiguration().screenLayout
                & Configuration.SCREENLAYOUT_SIZE_MASK)
                >= Configuration.SCREENLAYOUT_SIZE_LARGE);
    }
}

结果: 似乎工作正常,但不适用于其他操作系统:(

实验#2

让我们试试Qt Framework 工具。在这里,我可以了解具有 QScreen class 个实例的设备物理尺寸。作为 isTablet 的标准,我将使用 diagonal > 7.0 inches.

的条件
qreal Utils::getDiagInch() {
    QScreen *srn = qApp->screens().at(0);
    qreal w = srn->physicalSize().width();
    qreal h = srn->physicalSize().height();
    qreal inches = qSqrt(w * w + h * h) / 25.4; // millimeters to inches
    qDebug() << "physical diagonal >> " << inches;
    return inches;
}

对于实验,我使用了 HTC ONE X phone。

(qreal Utils::getDiagInch()): physical width >> 3.38583 (qreal Utils::getDiagInch()): physical height >> 6.02362 (qreal Utils::getDiagInch()): physical diagonal >> 6.90998

正如我们从官方制造商的属性中看到的那样,phone 有

width of 2.3 inches, height of 4.1 inches and diagonal of 4.7 inches

好的。有了不正确的值,我们无论如何得到了正确的结果:

HTC ONE X is PHONE as it has diagonal less than 7.0 inches.

结果: 该方法不可靠。

好的。另一个实验:

实验 #3

建议问题出在 Qt Framework 实现中,returning 值不正确。然后,如果我们询问 Android 显示物理尺寸的本机工具,它应该 return 不同的结果:

java-class:

public class MyActivityJo extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

        double physWidth = metrics.widthPixels / metrics.xdpi;
        Log.d("ph width >> ", Double.toString(physWidth));
        double physHeight = metrics.heightPixels / metrics.ydpi;
        Log.d("ph height >> ", Double.toString(physHeight));
        double physDiag = Math.sqrt(physWidth * physWidth + physHeight * physHeight);
        Log.d("ph diagonal >> ", Double.toString(physDiag));
    }
}

输出:

D/ph width >> (27948): 3.380281686782837 D/ph height >> (27948): 6.009389877319336 D/ph diagonal >> (27948): 6.894858300184821

结果: DisplayMetrics return 的值也不正确。

总体

我试过很多 playmarket 应用程序。他们知道如何准确回答这个问题:没有一个应用检测错误 tablet/phone。他们是怎么做到的?他们使用本地工具吗?还是Qt Framework有通用的、非原生的方法明确解决问题??

如果一定要获取屏幕的dpi值,可以按照这个方法:

在.pro

android{
QT += androidextras
}

包括

#if defined(Q_OS_ANDROID)
#include <QAndroidJniObject>
#endif

代码:

qreal m_dpi;
qreal m_pixelRatio;

#if defined(Q_OS_ANDROID)
QAndroidJniObject qtActivity =    QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
QAndroidJniObject resources = qtActivity.callObjectMethod("getResources","()Landroid/content/res/Resources;");
QAndroidJniObject displayMetrics = resources.callObjectMethod("getDisplayMetrics","()Landroid/util/DisplayMetrics;");
int density = displayMetrics.getField<int>("densityDpi");
m_dpi = density;
m_pixelRatio = 1;
#else
m_dpi = qApp->primaryScreen()->physicalDotsPerInch();
m_pixelRatio = qApp->primaryScreen()->devicePixelRatio();
#endif

获得 dpi 后,如果必须找到相对于参考设备的比例因子。

qreal m_dpiRef = 132; //reference device dpi (ipad);
double scalingFactor = 1;

if(m_dpi>0&&m_dpiRef >0)
 scalingFactor=m_dpi/m_dpiRef;

物理尺寸:

width/m_dpi //should give the physical width of screen in inches.

要在 android 设备中检查设备是平板电脑还是移动设备,最小宽度为 600dp 的 mdpi(160 dpi) android 设备可被视为平板电脑(可能会因您的要求而异) ).

width*160/m_dpi >= 600 //to check if the screen size is large enough(tablet). 

我已经验证了 Android 和 iOS 的代码。 您可能需要为 windows 使用以下代码。 (请验证)。

m_dpi = qApp->primaryScreen()->logicalDotsPerInch()*qApp->primaryScreen()->devicePixelRatio();