2014-07-07 99 views
0

我試圖通過JNI調用從C庫調用Java的getFilesDir(),並且遇到我不明白的NullPointerException。這裏的例外:在JNI調用中調用getFilesDir()時出現NullPointerException

W/System.err(1576): java.lang.NullPointerException 
W/System.err(1576): at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:109) 
W/System.err(1576): at MYService.getFilesDirPath(MYService.java:1150) 
W/System.err(1576): at MYService.UtvGetPeristentPath(Native Method) 

問題是在這個函數中發生的事情:

public String getFilesDirPath() 
{ 
    try { 
     return getFilesDir().getPath(); // <--- Exception happens here! 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
     Log.e("DEBUG", "getFilesDirPath set exception", e); 
     return null; 
    } 
} 

的JNI調用設置了由JNI_OnLoad設置一些靜態變量:

static JavaVM    *s_jvm = NULL; 
static jclass cls; 
static jmethodID mid; 
static jobject obj;       

jint JNI_OnLoad(JavaVM *vm, void *reserved) { 
    s_jvm = vm; 
    JNIEnv *env; 
    if (s_jvm){ 
     (*s_jvm)->AttachCurrentThread (s_jvm, &env, NULL); 
    }  
    jclass localRef_class; 
    jmethodID localRef_mid; 
    jmethodID constr; 

    localRef_class = (*env)->FindClass(env, "MYService"); 
    cls = (*env)->NewGlobalRef(env,localRef_class); 

    constr = (*env)->GetMethodID(env, cls, "<init>", "()V"); 
    obj = (*env)->NewGlobalRef(env, (*env)->NewObject(env, cls, constr)); 

    return JNI_VERSION_1_6; 
} 

這裏是JNI功能本身:

char *getFilesDirPath() { 
    JNIEnv *jenv = NULL; 
    __android_log_print(ANDROID_LOG_ERROR, "DEBUG", "JNI_Interface: getFilesDirPath"); 
    if(s_jvm == NULL) 
    return NULL; 

    int check = (*s_jvm)->GetEnv(s_jvm,(void **)&jenv,JNI_VERSION_1_6); 

    if (check != JNI_OK) { 
     (*s_jvm)->AttachCurrentThread(s_jvm, &jenv, NULL); 
     (*s_jvm)->GetEnv(s_jvm,(void **)&jenv,JNI_VERSION_1_6); 
    } 
    if(jenv != NULL) 
    { 

     // get the method 
     mid = (*jenv)->GetMethodID(jenv, cls, "getFilesDirPath", "()Ljava/lang/String;"); 
     if (mid == 0) { 
      __android_log_print(ANDROID_LOG_ERROR, "DEBUG", "getFilesDirPath not found"); 
      if (check != JNI_OK) 
       (*s_jvm)->DetachCurrentThread (s_jvm); 
      return NULL; 
     } 
     else{ 
      jstring result = (jstring)(*jenv)->CallObjectMethod(jenv, obj, mid); 
      char *filesDir = (char *) (*jenv)->GetStringUTFChars(jenv, result, 0); 
      if (check != JNI_OK) 
       (*s_jvm)->DetachCurrentThread (s_jvm); 
      return filesDir; 
     } 

    } 

    if (check != JNI_OK) 
     (*s_jvm)->DetachCurrentThread (s_jvm); 
    return NULL; 
} 

這個問題肯定與getFilesDir()有關。如果我避免調用該函數並傳回一個調試字符串,那麼一切似乎都有效。我認爲這個問題與沒有正確設置上下文有關,但我不確定什麼可能是錯誤的。

+0

我認爲你是正確的。您的MyService類可能擴展了Service或Activity。這些類不是用它們的構造函數調用創建的。它們由系統使用意圖啓動。您通常可以在其onCreate方法中使用完整的「上下文」功能。所以你應該從別的地方得到你的MyService的引用 - 而不是通過實例化它。 –

+0

謝謝,這有幫助。我在onCreate('mContext = this;)中保存了上下文,然後在getFilesDirPath()函數('mContext.getFilesDir()。getPath()')中使用它。請發表您的評論作爲答案,我會很樂意給你信用。 – GrandAdmiral

回答

1

您的MYService類可能會擴展Android服務或活動。這些類通常不是用它們的構造函數調用創建的。它們由系統使用Intents啓動。您通常可以在他們的onCreate方法中首次使用完整的「上下文」功能。所以你應該從其他地方獲得對你的MYService的引用 - 而不是通過從JNI實例化它。

相關問題