【问题标题】:persistent data to be retrieved using JNI in android在android中使用JNI检索持久数据
【发布时间】:2013-05-31 12:27:50
【问题描述】:

我正在编写一个 Android 应用程序,我需要有两个必须由应用程序读取的持久值。应用程序需要维护一个计数器,该计数器必须存储在“某处”并在每次启动 Activity 时检索。然后在关闭 Activity 之前更新并存储计数器。

重要的一点是我希望计数器的存储和检索由我的代码的 JNI 部分完成。它对 Java 代码实际上应该是不可见的。这个计数器(内存)可以使用 JNI 访问吗?如果是这样,您能指出我必须查看哪个 API 吗? 我知道可以在 Java 端使用 SQLiteDatabase。请指教!

【问题讨论】:

    标签: android android-ndk java-native-interface


    【解决方案1】:

    这是完全可能的,但不是没有一些 Java 代码。

    EDIT :提供以下内容作为数据库的替代品。能够从本机代码向文件读取和写入持久数据将比数据库灵活得多...

    假设您想从驻留在文件系统上的文件(二进制或纯文本)中存储和检索一些数据,这些将是要采取的步骤:

    1. JAVA : 获取应用的存储位置并检查它是否可用于读写

    2. JAVA : 如果上面是肯定的,通过JNI传给native层

    3. NATIVE:使用存储参数读取/写入文件

    好的,至此摘要;让我们来看看代码:

    1A) 检索和检查存储:

    private boolean checkExternalStorageState(){
            String state = Environment.getExternalStorageState();
    
            if (Environment.MEDIA_MOUNTED.equals(state)) {
                // We can read and write the media
                android.util.Log.i("YourActivity", "External storage is available for read/write...", null);
                return true;
            } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
                // We can only read the media : NOT ok
                android.util.Log.e("YourActivity", "External storage is read only...", null);
                return false;
            } else {
                // Something else is wrong. It may be one of many other states, but all we need
                //  to know is we can neither read nor write
                android.util.Log.e("YourActivity", "External storage is not mounted or read only...", null);
                return false;
            }
        }
    

    获取存储位置:

    private get storageLocation(){
        File externalAppDir = getExternalFilesDir(null);
        String storagePath = externalAppDir.getAbsolutePath()
    }
    

    1B) 您可能还想检查文件是否存在(您也可以在本机部分执行此操作)

    private boolean fileExists(String file) {
    
            String filePath = storagePath + "/" + file;
    
            // see if our file exists
            File dataFile = new File(filePath);
            if(dataFile.exists() && dataFile.isFile())
            {
                // file exists
                return true;
            }
            else
            {
                // file does not exist
                return false;
            }
        }
    

    2) 将其传递给原生层:

    JAVA部分:

    // Wrapper for native library
    public class YourNativeLib {
    
    
         static {
             // load required libs here
             System.loadLibrary("yournativelib");
         }
    
         public static native long initGlobalStorage(String storagePath);
         ...enter more functions here
    
    }
    

    原生部分:

    JNIEXPORT jlong JNICALL Java_com_whatever_YourNativeLib_initGlobalStorage(JNIEnv *env, jobject obj, jstring storagePath)
    {
        jlong data = 0;
    
        // convert strings
        const char *myStoragePath = env->GetStringUTFChars(storagepath, 0);
        // and now you can use "myStoragePath" to read/write files in c/c++
    
        //release strings
        env->ReleaseStringUTFChars(storagePath, myStoragePath);
    
        return data;
    }
    

    如何在 c/c++ 中读取/写入二进制文件或文本文件已有详细记录,我将由您决定。

    【讨论】:

    • 感谢您的回答。但我不明白的是,如果我知道文件的路径,为什么我需要从 Java 端传递它?我的代码的目的是以某种方式“隐藏”到 java 层所有关于计数器..
    • 此代码的唯一用途是检索并传递文件系统中的默认存储位置...它不知道任何计数器。您如何读取、写入或处理您的计数器可以完全在 c/c++ 中完成,并且对 java 是不可见的。但是 afaik 你需要 java 给你那个你可以读写的位置。
    【解决方案2】:

    您可以通过在项目中包含 SQLite 合并 (http://www.sqlite.org/download.html) 从 NDK 端使用 SQLite。

    SQLite with Android NDK

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-09
      • 2013-04-17
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      • 2011-05-11
      相关资源
      最近更新 更多