找回密码
 立即注册
收起左侧

Qt安卓开发经验001-010

0
回复
2542
查看
[复制链接]
累计签到:7 天
连续签到:1 天
来源: 2022-4-6 09:19:50 显示全部楼层 |阅读模式

马上注册,查看详细内容!注册请先查看:注册须知

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
项目作品37-安卓综合应用示例 https://qtchina.blog.csdn.net/article/details/123940153
1. pro中引入安卓拓展模块 QT += androidextras 。
2. pro中指定安卓打包目录 ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android 指定引入安卓特定目录比如程序图标、变量、颜色、java代码文件、jar库文件等。
- AndroidManifest.xml 每个程序唯一的一个全局配置文件,里面xml格式的数据,标明支持的安卓版本、图标位置、横屏竖屏、权限等。这个文件是最关键的,如果没有这个文件则Qt会默认生成一个。
- android/res/drawable-hdpi drawable-xxxhdpi 等目录下存放的是应用程序图标。
- android/res/layout 目录下存放的布局文件。
- android/res/values/libs.xml 存储的一些变量值。
- android/libs 目录下存放的jar库文件。
- android/src 目录下存放的java代码文件,可以是根据包名建立的一层层子目录,也可以直接在src目录下。
- 其他目录自行搜索安卓目录规范。
- 后面的说明统一用的android目录举例,其实你可以改成任意目录,比如你的代码目录下是xxoo存放的安卓相关的打包文件,你就写成 ANDROID_PACKAGE_SOURCE_DIR = $$PWD/xxoo 。

3. java类名必须和文件名完全一致,区分大小写。
4. java类必须在android/src目录下不然不会打包到apk文件,可以是子目录比如 android/src/com/qt 。
5. Qt代码中的QAndroidJniObject指定传入的java包名,必须严格和java文件package完全一致,不然程序执行到此处会因为找不到而崩溃。
- android/scr/MainActivity.java 顶部 没有 package 则代码中必须是 QAndroidJniObject javaClass("MainActivity");
- android/scr/MainActivity.java 顶部 package com.qandroid; 则代码中必须是 QAndroidJniObject javaClass("com/qandroid/MainActivity");
- android/scr/com/example/MainActivity.java 顶部 package com.qandroid; 则代码中必须是 QAndroidJniObject javaClass("com/qandroid/MainActivity");
- android/scr/com/example/MainActivity.java 顶部 package com.example.qandroid; 则代码中必须是 QAndroidJniObject javaClass("com/qandroid/example/MainActivity");
- 总之这个包名是和代码中的package后面一段吻合,而不是目录路径。为了统一管理方便查找文件,建议包名和目录路径一致。

6. Qt只能干Qt内部类的事情,做一些简单的UI交互还是非常方便,如果涉及到底层操作,还是需要熟悉java会如虎添翼,一般的做法就是写好java文件调试好,提供静态方法给Qt调用,这样通过QAndroidJniObject这个万能胶水可以做到Qt程序调用java中的函数并拿到执行结果,也可以接收java中的函数。
7. pro中通过 OTHER_FILES += android/AndroidManifest.xml OTHER_FILES += android/src/JniMessenger.java 引入文件其实对整个程序的编译打包没有任何影响,就是为了方便在QtCreator中查看和编辑。
8. 在Qt中与安卓的java文件交互都是用万能的QAndroidJniObject,可以执行java类中的普通函数、静态函数,可以传类对象jclass、类名className、方法methodName、参数,也可以拿到执行结果返回值。 (I)V括号中的是参数类型,括号后面的是返回值类型,void返回值对应V,由于String在java中不是数据类型而是类,所以要用Ljava/lang/String;表示,其他类作为参数也是这样处理。
- 调用实例方法:callMethod、callObjectMethod。
- 调用静态方法:callStaticMethod、callStaticObjectMethod。
- 不带Object的函数名用来执行无返回值或者常规返回值int、float等的方法。
- 如果返回值是String或者类则需要用带Object的函数名来执行,返回QAndroidJniObject类型再转换处理拿到结果,比如toString拿到字符串。

9. 各种参数和返回值示例。
  1. package org.qt;
  2. import org.qt.QtAndroidData;

  3. public class QtAndroidTest
  4. {
  5.     //需要通过实例来调用 测试发现不论 private public 或者不写都可以调用 我擦
  6.     private void printText()
  7.     {
  8.         System.out.println("printText");
  9.     }

  10.     public static void printMsg()
  11.     {
  12.         System.out.println("printMsg");
  13.     }

  14.     public static void printValue(int value)
  15.     {
  16.         System.out.println("printValue:" + value);
  17.     }

  18.     public static void setValue(float value1, double value2, char value3)
  19.     {
  20.         System.out.println("value1:" + value1 + " value2:" + value2 + " value3:" + value3);
  21.     }

  22.     public static int getValue()
  23.     {
  24.         return 65536;
  25.     }

  26.     public static int getValue(int value)
  27.     {
  28.         return value + 1;
  29.     }

  30.     public static void setMsg(String message)
  31.     {
  32.         System.out.println("setMsg:" + message);
  33.     }

  34.     public static String getMsg()
  35.     {
  36.         return "hello from java";
  37.     }

  38.     public static void setText(int value1, float value2, boolean value3, String message)
  39.     {
  40.         System.out.println("value1:" + value1 + " value2:" + value2 + " value3:" + value3 + " message:" + message);
  41.     }

  42.     public static String getText(int value1, float value2, boolean value3, String message)
  43.     {
  44.         //同时演示触发静态函数发给Qt
  45.         QtAndroidData.receiveData("message", "你好啊 java");

  46.         //下面两种办法都可以拼字符串
  47.         return "value1:" + value1 + " value2:" + value2 + " value3:" + value3 + " message:" + message;
  48.         //return "value1:" + String.valueOf(value1) + " value2:" + String.valueOf(value2) + " value3:" + String.valueOf(value3) + " message:" + message;
  49.     }
  50. }
  51. ```

  52. ```cpp
  53. #include "androidtest.h"

  54. //java类对应的包名+类名
  55. #define className "org/qt/QtAndroidTest"

  56. void AndroidTest::test()
  57. {
  58.     jint a = 12;
  59.     jint b = 4;
  60.     //可以直接调用java内置类中的方法
  61.     jint max = QAndroidJniObject::callStaticMethod<jint>("java/lang/Math", "max", "(II)I", a, b);

  62.     //jclass javaMathClass = "java/lang/Math";
  63.     jdouble value = QAndroidJniObject::callStaticMethod<jdouble>("java/lang/Math", "random");

  64.     qDebug() << "111" << max << value;
  65. }

  66. void AndroidTest::printText()
  67. {
  68.     QAndroidJniEnvironment env;
  69.     jclass clazz = env.findClass(className);
  70.     QAndroidJniObject obj(clazz);
  71.     obj.callMethod<void>("printText");
  72. }

  73. void AndroidTest::printMsg()
  74. {
  75. #if 0
  76.     //查看源码得知不传入jclass类的函数中内部会自动根据类名查找jclass
  77.     QAndroidJniEnvironment env;
  78.     jclass clazz = env.findClass(className);
  79.     QAndroidJniObject::callStaticMethod<void>(clazz, "printMsg");
  80. #else
  81.     //没有参数和返回值可以忽略第三个参数
  82.     QAndroidJniObject::callStaticMethod<void>(className, "printMsg");
  83.     //QAndroidJniObject::callStaticMethod<void>(classNameTest, "printMsg", "()V");
  84. #endif
  85. }

  86. void AndroidTest::printValue(int value)
  87. {
  88.     QAndroidJniObject::callStaticMethod<jint>(className, "printValue", "(I)I", (jint)value);
  89. }

  90. void AndroidTest::setValue(float value1, double value2, char value3)
  91. {
  92.     QAndroidJniObject::callStaticMethod<void>(className, "setValue", "(FDC)V", (jfloat)value1, (jdouble)value2, (jchar)value3);
  93. }

  94. int AndroidTest::getValue(int value)
  95. {
  96.     //java类中有两个 getValue 函数 一个需要传参数
  97.     //jint result = QAndroidJniObject::callStaticMethod<jint>(className, "getValue");
  98.     jint result = QAndroidJniObject::callStaticMethod<jint>(className, "getValue", "(I)I", (jint)value);
  99.     return result;
  100. }

  101. void AndroidTest::setMsg(const QString &msg)
  102. {
  103.     QAndroidJniObject jmsg = QAndroidJniObject::fromString(msg);
  104.     QAndroidJniObject::callStaticMethod<void>(className, "setMsg", "(Ljava/lang/String;)V", jmsg.object<jstring>());
  105. }

  106. QString AndroidTest::getMsg()
  107. {
  108.     QAndroidJniObject result = QAndroidJniObject::callStaticObjectMethod(className, "getMsg", "()Ljava/lang/String;");
  109.     return result.toString();
  110. }

  111. void AndroidTest::setText(int value1, float value2, bool value3, const QString &msg)
  112. {
  113.     QAndroidJniObject jmsg = QAndroidJniObject::fromString(msg);
  114.     QAndroidJniObject::callStaticMethod<void>(className, "setText", "(IFZLjava/lang/String;)V", (jint)value1, (jfloat)value2, (jboolean)value3, jmsg.object<jstring>());
  115. }

  116. QString AndroidTest::getText(int value1, float value2, bool value3, const QString &msg)
  117. {
  118.     QAndroidJniObject jmsg = QAndroidJniObject::fromString(msg);
  119.     QAndroidJniObject result = QAndroidJniObject::callStaticObjectMethod(className, "getText", "(IFZLjava/lang/String;)Ljava/lang/String;", (jint)value1, (jfloat)value2, (jboolean)value3, jmsg.object<jstring>());
  120.     return result.toString();
  121. }
复制代码


10. 在原生Android开发中,不同页面会定义不同的Activity。但使用Qt Quick、Flutter等采用Direct UI方式实现的第三方开发框架则只定义了一个Activity。里面不同页面实际都是使用OpenGL等直接绘制的。https://blog.csdn.net/LCSENs/article/details/100182235


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了