webentwicklung-frage-antwort-db.com.de

Wie erhalte ich die Android Pfadzeichenfolge zu einer Datei im Assets-Ordner?

Ich muss Zeichenfolgenpfad für eine Datei im Assets-Ordner kennen, da ich eine Karten-API verwende, die einen Zeichenfolgenpfad erhalten muss, und meine Karten müssen im Assets-Ordner gespeichert sein

Dies ist der Code, den ich versuche:

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

Mit "file:///Android_asset/m1.map" Läuft etwas schief, weil die Karte nicht geladen wird.

Welches ist die richtige String-Pfad-Datei zu der Datei m1.map , die in meinem Assets-Ordner gespeichert ist?

Vielen Dank

EDIT für Dimitru: Dieser Code funktioniert nicht, er schlägt bei is.read(buffer); mit IOException fehl

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

AFAIK die Dateien im Assets-Verzeichnis werden nicht entpackt. Stattdessen werden sie direkt aus der APK-Datei (Zip) gelesen.

Man kann also wirklich keine Sachen machen, die ein file erwarten, dass ein Asset 'file' akzeptiert.

Stattdessen müssen Sie das Asset extrahieren und in eine separate Datei schreiben, wie Dumitru vorschlägt:

  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());
89
Jacob Nordfalk

Sehen Sie sich ReadAsset.Java anhand der API-Beispiele an, die mit dem SDK geliefert werden.

       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);
    }
9
Dumitru Hristov

Sie können diese Methode verwenden.

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

Sie sollten in solchen Fällen niemals InputStream.available () verwenden. Es werden nur gepufferte Bytes zurückgegeben. Methode mit .available () funktioniert nie mit größeren Dateien und auf einigen Geräten überhaupt nicht.

In Kotlin (; D):

@Throws(IOException::class)
fun getRobotCacheFile(context: Context): File = File(context.cacheDir, "robot.png")
    .also {
        it.outputStream().use { cache -> context.assets.open("robot.png").use { it.copyTo(cache) } }
    }
9

Nur um Jaceks perfekte Lösung zu ergänzen. Wenn Sie versuchen, dies in Kotlin zu tun, wird es nicht sofort funktionieren. Stattdessen möchten Sie Folgendes verwenden:

@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
}
3
CheesusCrust