Search code examples
androidandroid-ndkjava-native-interface

persistent data to be retrieved using JNI in android


I am writing an Android App where I need to have two persistent values that have to be read by the App. The App needs to maintain a counter which has to be stored 'somehwhere' and retrieved each time the Activity is launched. The counter is then updated and then stored before the Activity is shut down.

The important point is that I want the storing and retrieval of the counter to be done by the JNI part of my code. It should be practically invisible to the Java code.. Can this counter(memory) be accessed using JNI? If so, can you point me to which API I have to look? I know one can use the SQLiteDatabase on the Java side. Please advise!


Solution

  • It's perfectly possible, but not without some Java code.

    EDIT : the following is offered as an alternative to a database. Being able to read and write persistent data to/from files from native code would be a lot more flexible than a database...

    Assuming you want to store and retrieve some data from a file (binary or plain text) residing on the filesystem these would be the steps to take:

    1. JAVA : get the storage location for your app and check if it's available for reading and writing

    2. JAVA : if the above is positive, pass it to the native layer through JNI

    3. NATIVE : use the storage params to read/write your file

    Ok, so far the abstract; lets get to the code:

    1A) retreiving and checking storage:

    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;
            }
        }
    

    Get the storage location :

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

    1B) you also might want to check if a file exists (you can also do this in the native part)

    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) Pass it to the native layer:

    JAVA part:

    // 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
    
    }
    

    NATIVE part:

    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;
    }
    

    How to read/write binary or text files in c/c++ is well documented, I'll leave that up to you.