簡體   English   中英

Android:需要在 C++ NDK 中創建共享首選項對象並存儲一些布爾值

[英]Android : Need to create Shared Preferences object in c++ NDK and Store some Boolean value

我是新手,不知道如何開始,

我創建了一個使用 Android.mk 鏈接到 C++ 的項目

因此,當我從 Java 調用方法時,它應該將布爾值存儲到我的共享首選項對象中。

這是我的 JNI 方法

extern "C"
JNIEXPORT void JNICALL
Java_com_example_sample_storeBoolean(JNIEnv *env,jobject instance){
//TODO 
const char *name ="hello";
__android_log_print(ANDROID_LOG_ERROR, "TRACKERS", "***** %s *****", name);
}

我打印的正常日志現在正在工作只需要創建 sharepreference 對象並設置布爾值

SharedPreferences prefs = context.getSharedPreferences("myprefdata", Context.MODE_PRIVATE);

prefs.edit().putBoolean("settingnootification", true).commit();

請指導我該怎么做。 謝謝

public abstract SharedPreferences getSharedPreferences(String name, int mode);

需要在c++中使用這個方法

我剛剛在 JNI 的 MainActivity 中調用saveBoolean(boolean bool)並保存了值。 這是代碼:MainActivity

public class MainActivity extends AppCompatActivity {

// Used to load the 'native-lib' library on application startup.
static {
    System.loadLibrary("native-lib");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    stringFromJNI(this);
}

/**
 * A native method that is implemented by the 'native-lib' native library,
 * which is packaged with this application.
 */
public native void stringFromJNI(MainActivity mainActivity);

public void saveBoolean(boolean bool){
    SharedPreferences sharedPreferences = this.getSharedPreferences("Test", Context.MODE_PRIVATE);
    sharedPreferences.edit().putBoolean("testBool",bool).commit();
    Log.d("MainActivity","saveBoolean Called "+bool);
}

}

#include <jni.h>
#include <string>

extern "C"
JNIEXPORT void JNICALL
Java_com_android_techgig_sharedpref_MainActivity_stringFromJNI(JNIEnv *env,jobject  obj /* this */) {

    jclass cls = (env)->GetObjectClass(obj); //for getting class
    jmethodID mid = (env)->GetMethodID(cls, "saveBoolean", "(Z)V"); //for getting method signature, Z for boolean
    if (mid == 0)
        return;
    //will return 0 in case of class not found
    (env)->CallVoidMethod(obj, mid, true); //now calling actual method
    printf("native called");
}

這是方法簽名類型

Signature   Java Type
Z   boolean
B   byte
C   char
S   short
I   int
J   long
F   float
D   double

這是探索更多的鏈接..

編碼快樂!!!

我猜您想從您的代碼中調用 Java 類。 我建議從您的 C++ 代碼中調用 Java。

看看這里:

https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo032

在此示例中,您要做的是:

  • Java調用C++
  • 基於從 Java 傳遞的信息,C++ 附加到 JVM
  • C++ 代碼從另一個類調用 Java 代碼(在您的情況下,它將是 SharedPreferences 對象)

您可能需要一些輔助類來簡化事情。 例如 PreferencesStorer - 您將在其中獲得適當的首選項類並傳遞要存儲的值。

看看這里:

public static int fun() {
  System.out.println("From JVM");
  return 0;
}

這是您要調用的方法,但您希望它是:store(String value, int mode)。

在您的代碼(Java 中)中,您需要創建此對象並將其作為參數傳遞給您的 C++ 代碼。 在 C++ 中,您想調用此對象的方法。 在 JVM 內部,它將已經存在——准備好被調用。

如果這不是您想要的,我認為您需要提供更多信息以使整個用例更加清晰。

玩得開心 JNI

我需要調用 getSharedPreferences() 方法,那么如何調用它並存儲布爾值。

因此,我創建了兩個用於在 NDK C++ 中存儲和檢索布爾值的簡單方法

主活動.java

public class MainActivity extends Activity {
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("Native");
    }
    private Activity activity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        activity=MainActivity.this;
        setStoreBoolValues(activity, true);

        if (getStoreValues(activity))
            Log.e("Store Value", " ** true **");
        else
            Log.e("Store Value", " ** false **");
    }

    public native boolean getStoreValues(Activity activity);
    public native void setStoreBoolValues(Activity activity, boolean flag);
}

在 MainActivity 中聲明了 Native Method,也調用了 my.so 文件

本機類.Cpp

jobject mainClass;

jstring spname(JNIEnv *env) {
    return env->NewStringUTF("sharedstore");
}

jstring objectname(JNIEnv *env) {
    return env->NewStringUTF("boolvaluestore");
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_ebizzinfotech_amjad_contentresolverproj_MainActivity_getStoreValues(JNIEnv *env,
                                                                             jobject instance,
                                                                             jobject activity) {

    jclass spcls = env->FindClass("android/content/SharedPreferences");
    jclass contextcls = env->FindClass("android/content/Context");
    mainClass = env->NewGlobalRef(activity);
    jmethodID mid = env->GetMethodID(contextcls, "getSharedPreferences",
                                     "(Ljava/lang/String;I)Landroid/content/SharedPreferences;");
    jmethodID midbool = env->GetMethodID(spcls, "getBoolean",
                                         "(Ljava/lang/String;Z)Z");
    jobject jobjectshared = env->CallObjectMethod(mainClass, mid, spname(env), 0);
//    jobject jobjectsharededit  = env->CallObjectMethod(jobjectshared,midedit);
    jboolean jboolean1 = env->CallBooleanMethod(jobjectshared, midbool,objectname(env), JNI_FALSE);

    env->DeleteLocalRef(spcls);
    env->DeleteLocalRef(contextcls);
    return jboolean1;
}


extern "C"
JNIEXPORT void JNICALL
Java_com_ebizzinfotech_amjad_contentresolverproj_MainActivity_setStoreBoolValues(JNIEnv *env,
                                                                                 jobject instance,
                                                                                 jobject activity,
                                                                                 jboolean flag) {
    jclass spcls = env->FindClass("android/content/SharedPreferences");
    jclass speditorcls = env->FindClass("android/content/SharedPreferences$Editor");
    jclass contextcls = env->FindClass("android/content/Context");

    mainClass = env->NewGlobalRef(activity);

    jmethodID mid = env->GetMethodID(contextcls, "getSharedPreferences",
                                     "(Ljava/lang/String;I)Landroid/content/SharedPreferences;");

    jmethodID midedit = env->GetMethodID(spcls, "edit",
                                         "()Landroid/content/SharedPreferences$Editor;");

    jmethodID midputbool = env->GetMethodID(speditorcls, "putBoolean",
                                            "(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor;");

    jmethodID midapply = env->GetMethodID(speditorcls, "apply",
                                          "()V");
    jobject jobjectshared = env->CallObjectMethod(mainClass, mid,spname(env), 0);
    jobject jobjectsharededit = env->CallObjectMethod(jobjectshared, midedit);
    env->CallVoidMethod(env->CallObjectMethod(jobjectsharededit, midputbool, objectname(env), flag),
                        midapply);
    env->DeleteLocalRef(spcls);
    env->DeleteLocalRef(contextcls);
    env->DeleteLocalRef(speditorcls);
}

我創建了兩個.cpp 類:用於讀取的SharedPreferences和用於寫入的SharedPreferences_Editor它們不需要任何特殊的Java 代碼,您應該能夠通過復制粘貼輕松地將它們包含在您的項目中。

//
// Created by Constantin on 24.10.2017.
//

#ifndef FPV_VR_HELPER_SHARED_PREFERENCES_HPP
#define FPV_VR_HELPER_SHARED_PREFERENCES_HPP

#include <jni.h>
#include <android/log.h>
#include <string>

///Example reading values
///SharedPreferences sharedPref(env,context,"pref_telemetry");
///T_Protocol=sharedPref.getInt(IDT::T_Protocol);
///Example writing values
///SharedPreferences_Editor editor=sharedPref.edit();
///editor.putString("MY_KEY","HELLO");
///editor.commit();

class SharedPreferences_Editor{
public:
    SharedPreferences_Editor(JNIEnv* env,const jobject joSharedPreferences_Edit):env(env),joSharedPreferences_Edit(joSharedPreferences_Edit){
        //find the methods for putting values into Shared preferences via the editor
        jclass jcSharedPreferences_Editor = env->GetObjectClass(joSharedPreferences_Edit);
        jmPutBoolean=env->GetMethodID(jcSharedPreferences_Editor,"putBoolean","(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor;");
        jmPutInt=env->GetMethodID(jcSharedPreferences_Editor,"putInt","(Ljava/lang/String;I)Landroid/content/SharedPreferences$Editor;");
        jmPutString=env->GetMethodID(jcSharedPreferences_Editor,"putString","(Ljava/lang/String;Ljava/lang/String;)Landroid/content/SharedPreferences$Editor;");
        jmCommit=env->GetMethodID(jcSharedPreferences_Editor,"commit","()Z");
    }
    //return itself for method chaining
    const SharedPreferences_Editor& putBoolean(const char* key,const bool value)const{
        env->CallObjectMethod(joSharedPreferences_Edit,jmPutBoolean,env->NewStringUTF(key),(jboolean)value);
        return *this;
    }
    const SharedPreferences_Editor& putInt(const char* key,const int value)const{
        env->CallObjectMethod(joSharedPreferences_Edit,jmPutInt,env->NewStringUTF(key),(jint)value);
        return *this;
    }
    const SharedPreferences_Editor& putString(const char* key,const char* value)const{
        env->CallObjectMethod(joSharedPreferences_Edit,jmPutString,env->NewStringUTF(key),env->NewStringUTF(value));
        return *this;
    }
    bool commit()const{
        return (bool)env->CallBooleanMethod(joSharedPreferences_Edit,jmCommit);
    }
private:
    JNIEnv* env;
    jobject joSharedPreferences_Edit;
    jmethodID jmPutBoolean;
    jmethodID jmPutInt;
    jmethodID jmPutString;
    jmethodID jmCommit;
};


class SharedPreferences {
public:
    SharedPreferences(SharedPreferences const &) = delete;
    void operator=(SharedPreferences const &)= delete;
public:
    //Note: Per default, this doesn't keep the reference to the sharedPreferences java object alive
    //longer than the lifetime of the JNIEnv.
    //With keepReference=true the joSharedPreferences is kept 'alive' and you can still use the class after the original JNIEnv* has become invalid -
    //but make sure to refresh the JNIEnv* object with a new valid reference via replaceJNI()
    SharedPreferences(JNIEnv *env, jobject androidContext,const char* name,const bool keepReference=false){
        this->env=env;
        //Find the 2 java classes we need to make calls with
        jclass jcContext = env->FindClass("android/content/Context");
        jclass jcSharedPreferences = env->FindClass("android/content/SharedPreferences");
        //jclass jcSharedPreferences_Editor=env->FindClass("android/content/SharedPreferences$Editor");
        if(jcContext==nullptr || jcSharedPreferences== nullptr){
            __android_log_print(ANDROID_LOG_DEBUG, "SharedPreferences","Cannot find classes");
        }
        //find the 3 functions we need to get values from an SharedPreferences instance
        jmGetBoolean=env->GetMethodID(jcSharedPreferences,"getBoolean","(Ljava/lang/String;Z)Z");
        jmGetInt=env->GetMethodID(jcSharedPreferences,"getInt","(Ljava/lang/String;I)I");
        jmGetFloat=env->GetMethodID(jcSharedPreferences,"getFloat","(Ljava/lang/String;F)F");
        jmGetString=env->GetMethodID(jcSharedPreferences,"getString","(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
        //find the 1 function we need to create the SharedPreferences.Editor object
        jmEdit=env->GetMethodID(jcSharedPreferences,"edit", "()Landroid/content/SharedPreferences$Editor;");
        //create a instance of SharedPreferences and store it in @joSharedPreferences
        jmethodID jmGetSharedPreferences=env->GetMethodID(jcContext,"getSharedPreferences","(Ljava/lang/String;I)Landroid/content/SharedPreferences;");
        joSharedPreferences=env->CallObjectMethod(androidContext,jmGetSharedPreferences,env->NewStringUTF(name),MODE_PRIVATE);
        //jmEdit_commit=env->GetMethodID(jcSharedPreferences_Editor,"putString","(Ljava/lang/String;Ljava/lang/String;)Landroid/content/SharedPreferences$Editor;");
        if(keepReference){
            joSharedPreferences=env->NewWeakGlobalRef(joSharedPreferences);
        }
    }
    void replaceJNI(JNIEnv* newEnv){
        env=newEnv;
    }
private:
    JNIEnv* env;
    jobject joSharedPreferences;
    jmethodID jmGetBoolean;
    jmethodID jmGetInt;
    jmethodID jmGetFloat;
    jmethodID jmGetString;
    jmethodID jmEdit;
public:
    bool getBoolean(const char* id,bool defaultValue=false)const{
        return (bool)(env->CallBooleanMethod(joSharedPreferences,jmGetBoolean,env->NewStringUTF(id),(jboolean)defaultValue));
    }
    int getInt(const char* id,int defaultValue=0)const{
        return (int)(env->CallIntMethod(joSharedPreferences,jmGetInt,env->NewStringUTF(id),(jint)defaultValue));
    }
    float getFloat(const char* id,float defaultValue=0.0f)const{
        return (float)(env->CallFloatMethod(joSharedPreferences,jmGetFloat,env->NewStringUTF(id),(jfloat)defaultValue));
    }
    std::string getString(const char* id,const char* defaultValue="")const{
        auto value=(jstring)(env->CallObjectMethod(joSharedPreferences,jmGetString,env->NewStringUTF(id),env->NewStringUTF(defaultValue)));
        const char* valueP = env->GetStringUTFChars(value, nullptr);
        const std::string ret=std::string(valueP);
        env->ReleaseStringUTFChars(value,valueP);
        //__android_log_print(ANDROID_LOG_DEBUG, "SharedPreferences","%s",ret.c_str());
        return ret;
    }
    SharedPreferences_Editor edit()const{
        //create a instance of SharedPreferences.Editor and store it in @joSharedPreferences_Edit
        jobject joSharedPreferences_Edit=env->CallObjectMethod(joSharedPreferences,jmEdit);
        SharedPreferences_Editor editor(env,joSharedPreferences_Edit);
        return editor;
    }
private:
    static constexpr const int  MODE_PRIVATE = 0; //taken directly from java, assuming this value stays constant in java
};


#endif //FPV_VR_HELPER_SHARED_PREFERENCES_HPP

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM