I have a file called Gate.IC inside my assets in my Android App.
I use this code to measure the length of the file in the assets:
private byte[] Buf = new byte[1024*512];
public int FileLength (String s)
{
int Count = 0;
try {
InputStream s2 = assetManager.open(s);
int tmp = 0;
while ((tmp=s2.read(Buf))>0)
Count+=tmp;
s2.close();
}
catch (IOException e) {
String Message = e.getMessage();
}
return Count;
}
This code works fine for all files except this one.
When it gets to this file, it does open it(and shows the correct file length), but when it reads it I get an IOException and the LogCat says "Error reading asset data" and then "Unable to access asset data: -1"
If I take a different file and change it's name to Gate.IC and don't have the actual Gate.IC file in the assets, it works.
If I change the name of the original Gate.IC into another asset's name, then I get the same error with the "cover" name.
I don't know what it is in this file that it just can't read it.
Here is the Rogue file:
https://dl.dropbox.com/u/8025882/RPG/Gate.IC
you can use this for getting length of the file:
getAssets().openFd( "filename" ).getLength();
I have solved the issue.
Well as I mentioend, it turns out ADT or the Android SDK packaging would compress some fo the assets. My file being my own custom format would be compressed.
Once your file is compressed you cannot read it the same way I did.
There is a program in Android SDK called aapt.exe. It does the packaging of the assets.
All you need to do is call this command with the flag -0 .
Sounds simple, right?
The issue is that eclipse does not let you add flags to this command from within the ADT plugin.
You need to either edit the Android SDK XML build files, or to replace aapt.exe with your own program that calls the original aapt.exe program with the flags you want.
I did the latter.
Here is my devblog entry about it.
http://pompidev.net/2012/10/27/unable-to-access-asset-data-1-and-compressed-assetsandroid/
Related
so i know there are alot of questions about creating a text file in android but i cant find any answers to my specific questions.
So the device I'm using is not an phone or a tablet, its a controller with android on it so the file directory is getting me confused. i want to create a new file either on the sd card or the device itself (it doesn't really matter as long as i can see it). firstly, the device doesn't have google docs or sheets or anything like that, will i need to install one of these apps on it for it to be able to read .txt files? or does android have some sort of internal software to do that?
Secondly, i've found alot of code on how to create a new file but most of it seems to gloss over how to get file directory, is there a specific way i can get the file directory?
This is what im using so far and im not getting any errors but its also not creating any files (or at-least none that i can see).
public void WriteToText(){
String FILENAME = "hello_file";
String string = "hello world!";
FileOutputStream fos = null;
try {
fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
1, I think all devices have Html viewer which can view the text files. If you click a text file in a file manager app, it should prompt you with a list of apps that can view the text file.
2, Your code is correct, but it creates a file in the app's private file directory, which is not visible to all other apps, including file manager apps. This is because of Android security policy to prevent any app to steal information from other apps.
If you want to write a file which is visible to other apps like file manager, there are 2 ways.
in old api level (<29?) you can get the get external storage with
Environment.getExternalStorageDirectory()
you will need to request permission for it.
save the file in your app's private directory like what you have done, then create a chooser to share it out with correct mime type (txt/plain?), it will prompt you to select app that can view this mime type like what file manager does.
I am attempting to parse a json file as part of an android development project. Here is the error message that keeps popping up:
W/System.err: java.nio.file.NoSuchFileException: C:/Users/andno/Desktop/AndroidDev2ClimateApp/app/src/main/java/com/example/androiddev2climateapp/ui/home/test.json
However, in android studios, the path in the error is supplied as a link, which I can click, leading me to the write file- thus, I don't think the path is wrong.
Here is my code:
String first = "C:/Users/andno/Desktop/AndroidDev2ClimateApp/app/src/main/java/com/example/androiddev2climateapp/ui/home/test.json";
try {
String fileContents = new String((Files.readAllBytes(Paths.get(first))));
JSONObject json = new JSONObject(fileContents);
JSONArray widgets = new JSONArray("WidgetArray");
for(int i = 0; i < widgets.length(); i++){
int id = widgets.getJSONObject(i).getInt("id");
System.out.println(id);
}
} catch(IOException | JSONException e){
e.printStackTrace();
}
Sorry that the formatting is messed up. I have tried using \ in the path instead of / as well, but it doesn't work. Any help would be greatly appreciated- thanks so much!
You may be able to get this code to work when you're testing, but obviously, there is no C:\Users\andno on your android phone and there never will be.
You're barking up the wrong tree. You don't want to read a file at all.
You want to read a resource from the same place java (or, rather, android) is loading the class file (or whatever passes for class file in android). Which is probably from within a jar or apk or whatnot.
UiMain.class.getResource("test.json")
or
UiMain.class.getResourceAsStream("test.json")
will get you a resource named test.json from the same place that UiMain.class is located (i.e. in the same package, I'm assuming this is class com.example.android.androiddev2climateapp.home.ui.UiMain. The first one as a URL, which you can usually pass to constructors of images and the like, and the second as stream, which you'd need to safely close (try/finally or try-with-resources if android has gotten around to adding that 20 year old java feature already), and which you can turn into a string using various APIs. Probably the JSON API itself can just be fed an inputstream.
My CodenameOne app is being tested on the iOS simulator (iPad 8th iOS 14).
It writes some files in the private folder by means of this method:
public void writeFile() throws IOException {
try(OutputStream os = FileSystemStorage.getInstance().openOutputStream(Utils.getRootPath()+DATA_FILE);)
{
os.write(JSONText.getBytes("UTF-8"));
os.flush();
os.close();
} catch(IOException err) {
System.out.println("exception trying to write");
}
}
It works on the CN simulator (writes inside the .cn1/ folder)
but on iOS the exception is catched. The Library folder is of paramount importance on iOS.
Below is the method to get the root path
public static String getRootPath()
{
String documentsRoot=FileSystemStorage.getInstance().getRoots()[0];
String os=Display.getInstance().getPlatformName();
if (os.toLowerCase().contains("ios")) {
int pos=documentsRoot.lastIndexOf("Documents");
if (pos==-1) return documentsRoot+"/";
String libraryRoot=documentsRoot.substring(0,pos)+"Library";
String result=libraryRoot+"/";
return result;
}
The CN version of my app has to write those private files in the same location as the swift version, that is Library.
There is string manipulation, and no extra '/' are added, the file path seems legit.
So the string
file:///Users/mac/Library/Developer/CoreSimulator/Devices/alphanumeric-string/data/Containers/Data/Application/another-alphanumeric-string/Documents/
is transformed and
the getRootPath() method returns
file:///Users/mac/Library/Developer/CoreSimulator/Devices/alphanumeric-string/data/Containers/Data/Application/another-alphanumeric-string/Library/
But there is exception.
Furthermore, at some point after the writing attempt, I see in the console output something I think is relevant:
Failed to create directory /Users/mac/Library/Developer/CoreSimulator/Devices/alphanumeric-string/data/Containers/Data/Application/another-alphanumeric-string/Documents/cn1storage/
What is this? Is it related to my problem?
Is CN filesystem access broken or flawed?
I know io access permissions are automatically created by the CN compiler, but are they working?
So how to fix my issue about the Library folder?
The cn1storage printout just means the storage directory already exists.
The way to get the library path is this: Getting an iOS application's "~/Library" path reliably
You need to use that approach. I think your assumption that Document and Library reside under the exact same hierarchy is just incorrect.
I am trying to output numeric values one at a time from an Android application I'm writing, but I'm having a lot of trouble figuring out what's going on. Tried looking for answers, but only confused further. This strikes me as something that should be relatively straightforward, so I feel pretty dumb for being so confused by it.
String directory = Environment.getExternalStorageDirectory().getAbsolutePath();
When I log the directory I get a path "/storage/emulated/0" Where is that? Is that different from what I would get if I wasn't debugging?
Then I have:
String fileName = directory + "/Android/data/com.sample.app/files/test.txt"
File myFile = new File(fileName);
FileOutputStream fos;
try {
fos = new FileOutputStream(myFile);
String text = "Test text\n";
fos.write(text.getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
I tried using the Windows Explorer to figure out where stuff is saving and/or is supposed to be saved but I don't see it. This is code based on the information in this link: http://developer.android.com/guide/topics/data/data-storage.html, but I really don't understand where the "/storage/emulated/0" comes from and how I either access that location or get rid of it.
EDIT: Right now I just want to save all the numbers so I can check what is coming out. The numbers are recorded from the audio input.
EDIT: Using the ASTRO File app on my phone revealed the files
Didn't need the "/Android/data/com.sample.app/files/" part, don't know how to use that.
Path wrong?
/storage/emulated/0 is a path at your filesystem which represents the external storage. At earlier versions of Android we often had /mnt/sdcard/ or something similiar, but many devices today don't have a sdcard but emulate an external storage anyway.
To view the files at your Android filesystem I'd recommend to use an App like Astro File Manager. Just take a look if your file has been written.
One possible mistake could be, that you you are missing a File.separator between your directory and the local path.
String fileName = directory + File.seperator + "Android/data/com.sample.app/file/test.txt"
Directory created?
You should also make sure, that the directory exists by calling myDir.mkDirs();, where myDir is the complete path without the filename.
To create the directory you can use the following code
directory = directory + "/Android/data/com.sample.app/file/test.txt"
new File(directory).mkDirs();
Uses-Permission in Manifest?
Last error source could be, that you might miss the external storage permission, you need a
You also need to make sure, that you require the permission for writing to the external storage. Take a look for <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in your Android Manifest file.
I am trying to learn how to use the Simple XML Framework as detailed in this thread : Best practices for parsing XML.
I am using the following code :
public class SimpleXMLParserActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
Serializer serializer = new Persister();
Example example = new Example("Example message", 123);
File result = new File("example.xml");
try {
Log.d("Start", "Starting Serializer");
serializer.write(example, result);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Self", "Error");
e.printStackTrace();
}
}
}
I am having a problem understanding the line
File result = new File("example.xml");
1) Does this line create a new file in my app called example.xml ? If so where is this file located.
2) Or does this line look for an existing file called example.xml and then add to it ? If so where should the example.xml file be placed in my app bundle so that it can be found. I do notice at the moment I am getting an error message :
java.io.FileNotFoundException: /example.xml (Read-only file system)
Thank you.
File result = new File("example.xml")
This line will just store the filename "example.xml" in a new File object. There is no check if that file actually exists and it does not try to create it either.
A file without specifying an absolute path (starting with / like new File("/sdcard/example.xml")) is considered to be in the current working directory which I guess is / for Android apps (-> /example.xml (Read-only file system))
I guess serializer.write(example, result); tries to create the actual file for your but fails since you can't write to '/'.
You have to specify a path for that file. There are several places you can store files, e.g.
Context#getFilesDir() will give you a place in your app's home directory (/data/data/your.package/files/) where only you can read / write - without extra permission.
Environment#getExternalStorageDirectory() will give you the general primary storage thing (might be /sdcard/ - but that's very different for devices). To write here you'll need the WRITE_EXTERNAL_STORAGE permission.
there are more places available in Environment that are more specialized. E.g. for media files, downloads, caching, etc.
there is also Context#getExternalFilesDir() for app private (big) files you want to store on the external storage (something like /sdcard/Android/data/your.package/)
to fix your code you could do
File result = new File(Environment.getExternalStorageDirectory(), "example.xml");
Edit: either use the provided mechanisms to get an existing directory (preferred but you are limited to the folders you are supposed to use):
// via File - /data/data/your.package/app_assets/example.xml
File outputFile = new File(getDir("assets", Context.MODE_PRIVATE), "example.xml");
serializer.write(outputFile, result);
// via FileOutputStream - /data/data/your.package/files/example.xml
FileOutputStream outputStream = openFileOutput("example.xml", Context.MODE_PRIVATE);
serializer.write(outputStream, result);
or you may need to create the directories yourself (hackish way to get your app dir but it should work):
File outputFile = new File(new File(getFilesDir().getParentFile(), "assets"), "example.xml");
outputFile.mkdirs();
serializer.write(outputFile, result);
Try to avoid specifying full paths like "/data/data/com.simpletest.test/assets/example.xml" since they might be different on other devices / Android versions. Even the / is not guaranteed to be /. It's safer to use File.separatorChar instead if you have to.
2 solutions to do it cleanly :
use openFileOutput to write a private file in the application private directory (which could be located in the internal memory or the external storage if the app was moved there). See here for a snippet
or use the File constructor to create the File anywhere your app has write access. This is if you want to store the file on the SDCard for example. Instantiating a file doesn't create it on the file system, unless you start writiung to it (with FileOutputStream for example)
I'd recommend approach 1, it's better for users because these files get erased when your app is uninstalled. If the file is large, then using the External Storage is probably better.
What I read on the Android pages, I see it creates a file with that name:
File constructor
I think it writes it to the /data/data/packagname directory
edit: the 'packagename' was not shown in the tekst above. I put it between brackets. :s
Try saving to /sdcard/example.xml.