Как получить путь ресурсов в коде JNI? - PullRequest
1 голос
/ 20 января 2020

У меня есть этот класс в Java:

package com.android.skeleton;

import org.libsdl.app.SDLActivity;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.app.Activity;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Log;

import android.content.res.AssetFileDescriptor;

public class MyActivity extends SDLActivity
{
    private static String TAG = "MyActivity";
    private static String RESOURCES_DIR = "images";
    private static String APP_RESOURCES_DIR = "resources";
    static AssetManager assetManager;
    static File uncompressedFilesDir;
    public String assetsPath;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

      assetManager = getAssets();

        SharedPreferences settings = getPreferences(MODE_PRIVATE);
        boolean assetsUncompressed = settings.getBoolean("assetsUncompressed", false);
        uncompressedFilesDir = getDir(APP_RESOURCES_DIR,MODE_PRIVATE);

    uncompressDir(RESOURCES_DIR,uncompressedFilesDir);
    SharedPreferences.Editor editor = settings.edit();
    editor.putBoolean("assetsUncompressed", true);
    editor.commit();
    assetsPath = getResourcesPath();
    }

    public void uncompressDir(String in, File out)
    {
        try
            {
                String[] files = assetManager.list(in);
                Log.w(TAG,"Uncompressing: " + files.length + " files");
                for(int i=0; i<files.length; i++)
                    {
                        Log.w(TAG,"Uncompressing: " + files[i]);
                        File fileIn = new File(in,files[i]);
                        File fileOut = new File(out,files[i]);

                        try
                            {
                                uncompressFile(fileIn,fileOut);
                            }
                        catch(FileNotFoundException e)
                            {
                                // fileIn is a directory, uncompress the subdir
                                if(!fileOut.isDirectory())
                                    {
                                        Log.w(TAG,"Creating dir: " + fileOut.getAbsolutePath());
                                        fileOut.mkdir();
                                    }
                                uncompressDir(fileIn.getPath(), fileOut);
                            }
                    }
            }
        catch(IOException e)
            {
                e.printStackTrace();
            }
    }

    public static String getResourcesPath()
    {
        return uncompressedFilesDir.getAbsolutePath();
    }

    public static void uncompressFile(File fileIn,File fileOut)
        throws IOException
    {
        InputStream in = assetManager.open(fileIn.getPath(),
                                           android.content.res.AssetManager.ACCESS_RANDOM);
        OutputStream out = new FileOutputStream(fileOut);

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0)
            {
                out.write(buf, 0, len);
            }

        in.close();
        out.close();
        Log.i(TAG,"File copied.");
    }
}

, и я хотел бы вызвать метод SDL_main в JNI:

int SDL_main(int argc, char **argv) {
  //const char *assets_path = "/data/data/com.android.skeleton/app_resources";
  // and change something like:
  const char *assets_path = getAssetsPath();
}

Я пытался:

static const char * getAssetsPath(void) {
   JNIEnv *env = (JNIEnv*)SDL_AndroidGetJNIEnv();
   jobject activity = (jobject)SDL_AndroidGetActivity();
   jclass cls =  (*env)->GetObjectClass(env, activity); 
   jfieldID fid = (*env)->GetFieldID(env, cls, "assetsPath", "S");
   jstring jstr = (jstring)(*env)->GetObjectField(env, activity, fid);
   const char *str = (*env)->GetStringUTFChars(env, jstr, 0);
   return str;
}

и оно сломало приложение в строке jfieldID fid.... Я думаю, это произошло потому, что у класса, который должен быть задан, нет переменной "assetsPath", но я не знаю, как узнать, какой класс ему дан.

Как мне это сделать?

...