Hi i have an xml file that contains the data I'm going to use to populate my app. i need to be able to read/write this file which i believe is not possible as it becomes a static resource in the assets folder. Is there a way on launch to copy this file to a location where i can use it in this way? or what is the best way to read and write a xml from a local resource?
Try this..
Yes you can not write file in the assets folder at run time. For info link1, link2
You can use below code copy from assets to sdcard then you can write it.
AssetManager assetManager = this.getAssets();
InputStream in = assetManager.open("yourxmlfile.xml");
File SDCardRoot = new File(Environment.getExternalStorageDirectory().toString()+"/Folder");
SDCardRoot.mkdirs();
File file = new File(SDCardRoot,"hello.xml");
FileOutputStream fileOutput = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int bufferLength = 0;
while((bufferLength = in.read(buffer)) > 0)
{
fileOutput.write(buffer, 0, bufferLength);
}
fileOutput.close();
And also don't forget to add read/write permission in manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Related
The code below works: it reads a file named "file.txt" which is located in the "assets" folder of the APK and stores it in a buffer. So far, so good:
String u = "content://com.example.app/file.txt:assets"
ContentResolver r = controls.activity.getContentResolver();
InputStream in = r.openInputStream(Uri.parse(u));
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = in.read(buffer);
while (n >= 0) {
out.write(buffer, 0, n);
n = in.read(buffer);
}
in.close();
return out.toByteArray();
If however the file I want to read is in a subfolder of assets, e.g. subfolder "sub", and I provide this Uri to the above code:
String u = "content://com.example.app/sub/file.txt:assets"
... then in this case I don't get anything. The file is there, as assets/sub/file.txt but the above code returns an empty buffer. The only change I made is to replace "file.txt" with "sub/file.txt" which points to where the file is stored.
What am I doing wrong? Is it wrong to create the uri string manually like that? I believe it's allowed to store files in assets subfolders... If that's allowed, how do I specify the path in the uri string?
Note that I'm not trying to give access to the file to another app, I just want to read my own file from my own APK's assets and put it in a buffer for internal use.
Any help is greatly appreciated!
Use AssetManager and its open() method. So, you would replace:
ContentResolver r = controls.activity.getContentResolver();
InputStream in = r.openInputStream(Uri.parse(u));
with:
AssetManager assets = controls.activity.getAssets();
InputStream in = assets.open("sub/file.txt");
I have a file myfile.vtpk in my application's "Assets" folder.
I'm trying to load this file file in my application using the following:
Uri vtpkUri = new Uri("file:///android_asset/myfile.vtpk");
ArcGISVectorTiledLayer vtpkLayer = new ArcGISVectorTiledLayer(vtpkUri);
MyMapView.Map.OperationalLayers.Add(vtpkLayer);
I get no error, but the file is never loaded.
How can I access this file in Android?
Thanks!
Since a file in your Assets folder is compiled into your APK, there is no "Uri" for a file in your assets folder, or any file in your APK for that matter. If you need to be able to pass a Uri, you would want to copy the Asset to your Document or other folder for your app and then get the Uri.
First create a method to take an read stream and write write stream and write your asset to a file:
private void ReadWriteStream(Stream readStream, Stream writeStream)
{
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = readStream.Read(buffer, 0, Length);
// write the required bytes
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = readStream.Read(buffer, 0, Length);
}
readStream.Close();
writeStream.Close();
}
Then get the read stream from the asset:
AssetFileDescriptor afd = Assets.OpenFd("filenameinAssetsfolder.ext");
var readStream = afd.CreateOutputStream();
Then create the path for the file and the write stream:
// This will be your final file path
var pathToWriteFile =
Path.Combine (System.Environment.GetFolderPath
(System.Environment.SpecialFolder.Personal),
"filenametowrite.ext");
FileStream writeStream =
new FileStream(pathToWriteFile,
FileMode.OpenOrCreate,
FileAccess.Write);
And finally call the copy method created above:
ReadWriteStream(readStream, writeStream);
Now you should be able to access the file with the path in pathToWriteFile.
EDIT: As per the comment below, try the following instead of getting an AssetFileDescriptor first. Replace:
AssetFileDescriptor afd = Assets.OpenFd("filenameinAssetsfolder.ext");
var readStream = afd.CreateOutputStream();
with:
Stream readStream = Assets.Open("filenameinAssetsfolder.ext");
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Android - How to determine the Absolute path for specific file from Assets?
I am trying to pass a file to File(String path) class. Is there a way to find absolute path of the file in assets folder and pass it to File(). I tried file:///android_asset/myfoldername/myfilename as path string but it didnt work. Any idea?
AFAIK, you can't create a File from an assets file because these are stored in the apk, that means there is no path to an assets folder.
But, you can try to create that File using a buffer and the AssetManager (it provides access to an application's raw asset files).
Try to do something like:
AssetManager am = getAssets();
InputStream inputStream = am.open("myfoldername/myfilename");
File file = createFileFromInputStream(inputStream);
private File createFileFromInputStream(InputStream inputStream) {
try{
File f = new File(my_file_name);
OutputStream outputStream = new FileOutputStream(f);
byte buffer[] = new byte[1024];
int length = 0;
while((length=inputStream.read(buffer)) > 0) {
outputStream.write(buffer,0,length);
}
outputStream.close();
inputStream.close();
return f;
}catch (IOException e) {
//Logging exception
}
return null;
}
Let me know about your progress.
Unless you unpack them, assets remain inside the apk. Accordingly, there isn't a path you can feed into a File. The path you've given in your question will work with/in a WebView, but I think that's a special case for WebView.
You'll need to unpack the file or use it directly.
If you have a Context, you can use context.getAssets().open("myfoldername/myfilename"); to open an InputStream on the file. With the InputStream you can use it directly, or write it out somewhere (after which you can use it with File).
I'm reading files from a ZIP file that's located in my Android assets folder using ZipInputStream: it works, but it's really slow, as it has to read it sequentially using getNextEntry(), and there are quite a lot of files.
If I copy the ZIP file onto the SD card, reading is really fast when using ZipFile.getEntry, but I didn't find a way to use ZipFile with the asset file!
Is there any way to access the ZIP in the asset folder in a speedy way? Or do I really have to copy the ZIP to the SD card?
(BTW, in case anybody wonders why I'm doing this: the app is larger than 50 MB, so in order to get it in the Play Store I have to use Expansion APKs; however, as this app should also be put into the Amazon App Store, I have to use another version for this, as Amazon doesn't support Expansion APKs, naturally... I thought that accessing a ZIP file at two different locations would be an easy way to handle this, but alas...)
This works for me:
private void loadzip(String folder, InputStream inputStream) throws IOException
{
ZipInputStream zipIs = new ZipInputStream(inputStream);
ZipEntry ze = null;
while ((ze = zipIs.getNextEntry()) != null) {
FileOutputStream fout = new FileOutputStream(folder +"/"+ ze.getName());
byte[] buffer = new byte[1024];
int length = 0;
while ((length = zipIs.read(buffer))>0) {
fout.write(buffer, 0, length);
}
zipIs.closeEntry();
fout.close();
}
zipIs.close();
}
You can store the uncompressed files directly in assets (i.e. unpack the zip into assets/ folder). This way, you can access the files directly and they will be compressed anyway when you build the APK.
You can create a ZipInputStream in the following way :
ZipInputStream zipIs = new ZipInputStream(context.getResources().openRawResource(your.package.com.R.raw.filename));
ZipEntry ze = null;
while ((ze = zipIs.getNextEntry()) != null) {
FileOutputStream fout = new FileOutputStream(FOLDER_NAME +"/"+ ze.getName());
byte[] buffer = new byte[1024];
int length = 0;
while ((length = zipIs.read(buffer))>0) {
fout.write(buffer, 0, length);
}
zipIs .closeEntry();
fout.close();
}
zipIs .close();
I am currently trying to figure out a way to write a media file to internal/external storage (primary storage). The file to be saved could be any size from a few MBs to 50MBs. I have logic that works on my Droid X 2.3.3 Razr 2.3.5 (I believe) but does not work on my Galaxy Nexus (has no removable storage but a built in 16Gig card with v4.0.2). I have looked around and haven't found any code/samples that work with v4.0. Maybe I am approaching this all wrong since it doesn't have an actual sd card? maybe it is something new in v4.0? Currently when I run my application on the Galaxy Nexus I get this: System.err(19520): java.io.FileNotFoundException:
UPDATED
InputStream inputStream = urlConnection.getInputStream();
File PATH = Environment.getExternalStorageDirectory();
File FILE = new File(Environment.getExternalStorageDirectory()+ "/" + FILENAME);
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
// buffer int bufferSize = 1024; int bufferLength = 0; byte[] buffer = new byte[bufferSize];
while ((bufferLength = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, bufferLength);
}
byte[] temp = byteBuffer.toByteArray();
FileOutputStream fos = new FileOutputStream(FILE);
fos.write(temp);
fos.close();
Are you putting this file in a specific directory on your sdcard?external storage?
I assume your permissions in your manifest are good because the 'permission denied is not raised' so maybe if you put the file in a specific folder, which is not created you should call the mkdirs() function on your file!
First, don't convert it to a string, just use getExternalStorageDirectory() as a File:
File sd = Environment.getExternalStorageDirectory();
File file = new File(sd, FILENAME);
I don't know if that will correct it or not, but it wouldn't hurt to try that. And you do not need to call file.createNewFile() before writing to the file with a FileOutputStream. The docs about FileOutputStream say:
An output stream that writes bytes to a file. If the output file
exists, it can be replaced or appended to. If it does not exist, a new
file will be created.
And which line of code is the FileNotFoundException happening on?