Как получить строку android Path в файл в папке "Активы"?

Мне нужно знать путь строки к файлу в папке с ресурсами, потому что я использую карту api, которая должна получать строковый путь, а мои карты должны храниться в папке с ресурсами

Это код, который я пытаюсь:

    MapView mapView = new MapView(this);
    mapView.setClickable(true);
    mapView.setBuiltInZoomControls(true);
    mapView.setMapFile("file:///android_asset/m1.map");
    setContentView(mapView);

Что-то идет не так с "file:///android_asset/m1.map", потому что карта не загружается.

Каков правильный файл пути строки к файлу m1.map, хранящемуся в моей папке с ресурсами?

Спасибо

EDIT для Dimitru: этот код не работает, он терпит неудачу на is.read(buffer); с IOException

        try {
            InputStream is = getAssets().open("m1.map");
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
            text = new String(buffer);
        } catch (IOException e) {throw new RuntimeException(e);}

Ответ 1

AFAIK файлы в каталоге ресурсов не распаковываются. Вместо этого они считываются непосредственно из файла APK (ZIP).

Итак, вы действительно не можете создать материал, ожидающий, что файл примет файл актива.

Вместо этого вам нужно будет извлечь актив и записать его в отдельный файл, например, Dumitru предлагает:

  File f = new File(getCacheDir()+"/m1.map");
  if (!f.exists()) try {

    InputStream is = getAssets().open("m1.map");
    int size = is.available();
    byte[] buffer = new byte[size];
    is.read(buffer);
    is.close();


    FileOutputStream fos = new FileOutputStream(f);
    fos.write(buffer);
    fos.close();
  } catch (Exception e) { throw new RuntimeException(e); }

  mapView.setMapFile(f.getPath());

Ответ 2

Взгляните на образцы ReadAsset.java из API, которые поставляются вместе с SDK.

       try {
        InputStream is = getAssets().open("read_asset.txt");

        // We guarantee that the available method returns the total
        // size of the asset...  of course, this does mean that a single
        // asset can't be more than 2 gigs.
        int size = is.available();

        // Read the entire asset into a local byte buffer.
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();

        // Convert the buffer into a string.
        String text = new String(buffer);

        // Finally stick the string into the text view.
        TextView tv = (TextView)findViewById(R.id.text);
        tv.setText(text);
    } catch (IOException e) {
        // Should never happen!
        throw new RuntimeException(e);
    }

Ответ 3

Вы можете использовать этот метод.

    public static File getRobotCacheFile(Context context) throws IOException {
        File cacheFile = new File(context.getCacheDir(), "robot.png");
        try {
            InputStream inputStream = context.getAssets().open("robot.png");
            try {
                FileOutputStream outputStream = new FileOutputStream(cacheFile);
                try {
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = inputStream.read(buf)) > 0) {
                        outputStream.write(buf, 0, len);
                    }
                } finally {
                    outputStream.close();
                }
            } finally {
                inputStream.close();
            }
        } catch (IOException e) {
            throw new IOException("Could not open robot png", e);
        }
        return cacheFile;
    }

Вы должны никогда не использовать InputStream.available() в таких случаях. Он возвращает только байты, которые буферизуются. Метод с .available() никогда не будет работать с большими файлами и вообще не будет работать на некоторых устройствах.

Ответ 4

Просто добавьте идеальное решение Jacek. Если вы пытаетесь сделать это в Котлине, это не сработает сразу. Вместо этого вы захотите использовать это:

@Throws(IOException::class)
fun getSplashVideo(context: Context): File {
    val cacheFile = File(context.cacheDir, "splash_video")
    try {
        val inputStream = context.assets.open("splash_video")
        val outputStream = FileOutputStream(cacheFile)
        try {
            inputStream.copyTo(outputStream)
        } finally {
            inputStream.close()
            outputStream.close()
        }
    } catch (e: IOException) {
        throw IOException("Could not open splash_video", e)
    }
    return cacheFile
}