如何从C QT 5.6 Android拨打GetMemoryInfo?我不确定在调用GetSystemservice API时从Java/Lang/Object铸造到Android/App/ActivationManager,但我得到有效的qandroidjniobject btw。这是我到目前为止的代码。
osinfoandroid.h
#ifndef OSINFOANDROID_H
#define OSINFOANDROID_H
#include <QObject>
class OsInfoAndroid : public QObject {
Q_OBJECT
public:
explicit OsInfoAndroid(QObject *parent = 0);
~OsInfoAndroid();
public Q_SLOTS:
void testgetmeminfo();
};
#endif // OSINFOANDROID_H
osinfoandroid.cpp
#include "osinfoandroid.h"
#include <QDebug>
#include <QtAndroidExtras/QtAndroidExtras>
OsInfoAndroid::OsInfoAndroid(QObject *parent) : QObject(parent) {}
OsInfoAndroid::~OsInfoAndroid() {}
void OsInfoAndroid::testgetmeminfo() {
QAndroidJniObject cntact_service = QAndroidJniObject::getStaticObjectField(
"android/content/Context", "ACTIVITY_SERVICE", "Ljava/lang/String;");
if (cntact_service.isValid()) {
qDebug() << Q_FUNC_INFO << "ACTIVITY_SERVICE OK GOT INTERNAL STRING";
} else {
qDebug() << Q_FUNC_INFO << "ACTIVITY_SERVICE sad got nothing :(";
}
QAndroidJniObject ctx = QtAndroid::androidActivity().callObjectMethod(
"getApplicationContext", "()Landroid/content/Context;");
if (ctx.isValid()) {
qDebug() << Q_FUNC_INFO << "got valid context";
} else {
qDebug() << Q_FUNC_INFO << "sad got nothing context";
}
QAndroidJniObject actmgr = ctx.callObjectMethod(
"getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;",
cntact_service.object<jstring>());
if (actmgr.isValid()) {
qDebug() << Q_FUNC_INFO << "ok got ActivityManager";
QAndroidJniObject meminfo("android/app/ActivityManager$MemoryInfo");
if(!meminfo.isValid ()){
qDebug()<<Q_FUNC_INFO<<"SAD GOT INVALID MemoryInfo!";
return;
}
qDebug()<<Q_FUNC_INFO<<"ok got valid MemoryInfo";
//CRASH HERE
QAndroidJniObject voidmeminfo = actmgr.callObjectMethod(
"getMemoryInfo", "(Landroid/app/ActivityManager$MemoryInfo;)V",
meminfo.object<jclass>());
if (voidmeminfo.isValid()) {
qDebug() << Q_FUNC_INFO << "OK CALLING getMemoryInfo FROM CPP SUKSES!! ";
} else {
qDebug() << Q_FUNC_INFO << "calling from c++ failed!!";
}
}
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <osinfoandroid.h>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
OsInfoAndroid osinfo;
engine.rootContext ()->setContextProperty ("osinfo",&osinfo);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
androidmanifest.xml
<?xml version="1.0"?>
<manifest package="org.androidgetmeminfocrash" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<!-- Splash screen -->
<!--
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
-->
<!-- Splash screen -->
<!-- Background running -->
<!-- Warning: changing this value to true may cause unexpected crashes if the
application still try to draw after
"applicationStateChanged(Qt::ApplicationSuspended)"
signal is sent! -->
<meta-data android:name="android.app.background_running" android:value="false"/>
<!-- Background running -->
<!-- auto screen scale factor -->
<meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
<!-- auto screen scale factor -->
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.HARDWARE_TEST"/>
</manifest>
整个项目可以在此处下载
好吧,这个问题看起来像是从这里打电话
QAndroidJniObject voidmeminfo = actmgr.callObjectMethod(
"getMemoryInfo", "(Landroid/app/ActivityManager$MemoryInfo;)V",
meminfo.object<jclass>());
可以更改为
actmgr.callMethod<void>(
"getMemoryInfo", "(Landroid/app/ActivityManager$MemoryInfo;)V",
meminfo.object<jobject>());
但是我不确定哪个是正确的,无论使用meminfo.Object&lt;jobject>());或meminfo.Object&lt;jclass>());
所以,我想获取Android MemoryInfo availmem对象字段,在调用getMemoryInfo函数后,我添加此代码
QAndroidJniObject availmem=meminfo.getObjectField("availMem","J");
if(!availmem.isValid ()){
qDebug() << Q_FUNC_INFO << "calling from c++ failed!!";
}
但是,上面的代码仍会在Android Jelly Bean上产生明显的崩溃,任何指针?
我想实现的等价Java代码是这样的
ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "n" );
现在,我正在使用基于上述项目源下载的全Java主体功能的第二种方法。尝试从C 发出有效的活动上下文,并在Java中调用普通静态方法。然后创建文件夹com-> getmemorycrash文件夹。然后我创建一个Java文件Osinfo.java,所以现在我的getMemoryinfo.pro变得像这样
QT += qml quick androidextras
CONFIG += c++11
SOURCES += main.cpp osinfoandroid.cpp
HEADERS += osinfoandroid.h
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES +=
android/AndroidManifest.xml
android/gradle/wrapper/gradle-wrapper.jar
android/gradlew
android/res/values/libs.xml
android/build.gradle
android/gradle/wrapper/gradle-wrapper.properties
android/gradlew.bat
android/src/com/getmemorycrash/OsInfo.java
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
osinfo.java
package com.getmemorycrash;
import java.lang.Object;
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import java.lang.String;
import android.content.Context;
import android.util.Log;
public class OsInfo {
static long getMemavail(Context context ){
Log.d("ada","executing getMemavail");
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
Log.i("mydebug", " memoryInfo.availMem " + memoryInfo.availMem + "n" );
return memoryInfo.availMem;
}
}
最终的osinfoandroid.cpp,我添加了testgetmeminfomethod2函数,并以下代码
void OsInfoAndroid::testgetmeminfomethod2()
{
QAndroidJniObject ctx = QtAndroid::androidActivity().callObjectMethod(
"getApplicationContext", "()Landroid/content/Context;");
if (ctx.isValid()) {
qDebug() << Q_FUNC_INFO << "got valid context";
} else {
qDebug() << Q_FUNC_INFO << "sad got nothing context";
}
//crash here
QAndroidJniObject availmem=QAndroidJniObject::callStaticObjectMethod("com/getmemorycrash/OsInfo",
"getMemavail",
"(Landroid/content/Context;)J",
ctx.object<jclass>());
if(!availmem.isValid ()){
qDebug() << Q_FUNC_INFO << "calling from c++ failed!!";
}
}
那么,我的问题是为什么以上函数再次变成segfault?执行Java代码直到log android函数和然后立即发生崩溃,完全在返回时发生?
谢谢
好吧,我最终可以修复此问题,如果它们是原始类型的公共成员Java类变量的正确函数,我可以使用上述情况使用第一种方法而不是中继来基于上述情况在qandroidjniobject上
jlong availmem=meminfo.getField<jlong>("availMem");