2017-02-18 20 views
1

C++에서 getMemoryInfo를 호출하는 방법 5.6 android? Im는 getSystemService API를 호출 할 때 Java/lang/Object에서 android/app/ActivityManager로 캐스팅하지 않을 것이지만 유효한 QAndroidJniObject btw를 얻습니다. 지금까지 제 코드가 있습니다.qt androidextras getMemoryInfo MemoryInfo availMem C++에서 object 필드가 충돌합니다.

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

전체 프로젝트를 다운로드 할 수 있습니다 here

확인 문제는

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 사용 여부를 수정하십시오 < jobject>()); 또는 meminfo.object < jclass>());

그래서, 나는 여전히 안드로이드 젤리 빈에있는 포인터를 명백한 충돌을 생산하는 위의 코드이 코드

QAndroidJniObject availmem=meminfo.getObjectField("availMem","J"); 
if(!availmem.isValid()){ 
    qDebug() << Q_FUNC_INFO << "calling from c++ failed!!"; 
} 

를 추가하지만 getMemoryInfo 함수를 호출 한 후 안드로이드 MemoryInfo availMem 개체 필드를 얻으려면?

내가 달성하고자하는 등가 자바 코드 나는 위의 프로젝트 소스 다운로드를 기반으로 전체 자바 신체 기능과 두 번째 방법을 사용하고, 그래서 지금이 하나

ActivityManager activityManager = (ActivityManager)  context.getSystemService(ACTIVITY_SERVICE); 
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); 
activityManager.getMemoryInfo(memoryInfo); 

Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n"); 

같은 것입니다. 을 C++에서 유효한 활동 컨텍스트로 내보내고 java에서 일반 정적 메서드를 호출하십시오. 그런 다음 폴더 com-> getmemorycrash 폴더를 만듭니다. 는 그리고 자바 파일 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!!"; 
} 
} 

그래서 제 질문은 왜 기능이 다시 세그 폴트가됩니까? Java 코드는 Log android 함수가 실행될 때까지 실행되고 즉각적인 충돌이 발생하면 정확히 반환됩니다.

감사

답변

0

좋아, 나는 결국 첫 번째 방법을 사용하는 대신 QAndroidJniObject에 릴레이 위의 경우에 따라 내가 이것을 사용할 수 있습니다, 그들은 기본 유형 인 경우 public 멤버 자바 클래스 변수를 얻기 위해 올바른 기능을이 문제를 해결할 수 있습니다

jlong availmem=meminfo.getField<jlong>("availMem");