programacion - ¿Cómo obtener la cadena de ruta de acceso de Android a un archivo en la carpeta de Activos?
manual android studio avanzado (4)
Necesito saber la ruta de acceso de cadena a un archivo en la carpeta de activos, porque estoy usando una API de mapa que necesita recibir una ruta de cadena, y mis mapas deben almacenarse en la carpeta de activos.
Este es el código que intento:
MapView mapView = new MapView(this);
mapView.setClickable(true);
mapView.setBuiltInZoomControls(true);
mapView.setMapFile("file:///android_asset/m1.map");
setContentView(mapView);
Algo anda mal con "file:///android_asset/m1.map"
porque el mapa no se está cargando.
¿Cuál es el archivo de ruta de cadena correcto para el archivo m1.map almacenado en mi carpeta de activos?
Gracias
EDIT para Dimitru: Este código no funciona, falla is.read(buffer);
con 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);}
AFAIK los archivos en el directorio de activos no se desempaquetan. En cambio, se leen directamente desde el archivo APK (ZIP).
Entonces, realmente no puedes hacer cosas que esperen que un archivo acepte un "archivo" de activos.
En cambio, tendrá que extraer el activo y escribirlo en un archivo separado, como sugiere 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());
Eche un vistazo al ReadAsset.java de ejemplos de API que vienen con el 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);
}
Puedes usar este método
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;
}
Nunca debe usar InputStream.available () en tales casos. Devuelve solo los bytes que están almacenados en el búfer. El método con .available () nunca funcionará con archivos más grandes y no funcionará en algunos dispositivos.
Solo para agregar la solución perfecta de Jacek. Si intentas hacer esto en Kotlin, no funcionará de inmediato. En cambio, querrás usar esto:
@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
}