Why can't I open files in writing mode in C? I surely have all permisions, and the path is correct because it can be open in read mode. For example:
file = fopen(path, "r"); returns a correct file, but
file = fopen(path, "w"); always return null
In the Java part I can write the file, so, the solution I found is write the data in a C array and return it to Java
I see that in other questions or programs people can write in C... is a problem of new Android versions?
Related
I'm using Xamarin, C# and Monogame and I'm taking a fully-working Desktop game and porting it over to Android.
My problem is that I have this "Content folder" that you would always use in the Desktop version of the app. But I cannot access it or any other folder through the code directly using Android.
basicShader = new Effect(game1.GraphicsDevice,System.IO.File.ReadAllBytes("Content/TextureShader.mgfxo"));
This works just fine in the Desktop app but throws System.IO.DirectoryNotFoundException:'Could not find a part of the path "/Content/TextureShader.mgfxo".' on Android.
I'd like to mention that I already had the code and the project working perfectly when it was a desktop program. I also have a private class-level variable string[] list_of_files and in the constructor, I had the line list_of_files = Directory.GetFiles("./Content","*.txt");
This is for saving and loading player data. It may have been rudimentary but I had a fully functioning program that saved and loaded data on my computer. I am transitioning this program to be an Android app and this is the only part of the project that isn't working. When I run the code as it was originally written, I get "System.IO.DirectoryNotFoundException: 'Could not find a part of the path '/Content'.' ".
I've tried playing around with trying to read the contents of different folders.
I've messed around with different paths, including the Resources folder instead.
I added <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> to my manifest.
I know that I'm trying to access internal storage, not external, so I also tried <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" /> just to see if that might work.
Nothing works.
In another stack overflow post, a guy commented:
For the people who are facing NullPointerException - you are trying to access the files in the app's internal storage which are private sorry you can't do that. –
coderpc
Jun 23, 2017 at 16:00
I cannot imagine why this would be true. Why would a programmer not be able to write a program that can access it's own internal storage? That makes no sense to me. Obviously my app needs to be able to read and write it's own internal storage! And if this is true, then how else can I save persistent data on my phone? I don't want a database or a shared thingamabobber that uses key-value pairs, I have a self-made system that works as a text file and I want to continue to use it. I refuse to believe that an Android app can't keep track of a simple .txt file in one of it's own folders, that's just too hard for me to imagine. It can't be true.
I wanted to ask the commenter about his comment but Stack Overflow wouldn't let me because I don't have over 50xp.
Just like CommonsWare sayed, you can use the Intent.ActionOpenDocument to get the uri of the file. Such as
static readonly int READ_REQUEST_CODE = 1337;
Intent intent = new Intent(Intent.ActionOpenDocument);
intent.AddCategory(Intent.CategoryOpenable);
intent.SetType("*/*");
StartActivityForResult(intent, READ_REQUEST_CODE);
And override the OnActivityResult method:
if (requestCode == READ_REQUEST_CODE && resultCode == Result.Ok)
{
// The document selected by the user won't be returned in the intent.
// Instead, a URI to that document will be contained in the return intent
// provided to this method as a parameter. Pull that uri using "resultData.getData()"
if (data != null)
{
Android.Net.Uri uri = data.Data;
DocumentFile documentFile = DocumentFile.FromSingleUri(this.ApplicationContext,uri);
// Then you can operate the file with input and output stream
}
}
More information please check the simple on the github:
https://github.com/xamarin/monodroid-samples/blob/main/StorageClient/StorageClientFragment.cs
In addition, if you can ensure the file's path. You can use the StreamWriter and the StreamReader to write and read the file. Such as:
using (StreamWriter sw = new StreamWriter(path))
{
sw.WriteLine(content);
}
Furthermore, you can try to create the content folder and the txt file in the Android with the following code.
var filename1 = Android.App.Application.Context.GetExternalFilesDir(System.DateTime.Now.ToString("Content")).AbsolutePath;
var filename = System.IO.Path.Combine(filename1, "xxx.txt");
using (System.IO.FileStream os = new System.IO.FileStream(filename, System.IO.FileMode.Create))
{
}
The folder and the files created by this way belongs to the app and you can access it easily.
You can read the official document about the storage in the Android.
Link : https://developer.android.com/training/data-storage/shared/documents-files
In my app I have to pass a file from assets folder to shared library.
I cannot do it with use of jni right now.
I'm using precompiled shared library in my project, in which I have hardcoded path to my file, but I'm getting error "No such file or directory".
So in my .apk file I have .so file in libs/armeabi-v7a folder and my file in /assets folder.
I have tried to do it like this:
char *cert_file = "/assets/cacert.cert";
av_strdup(cert_file);
And some other paths, but it doesn't work.
Is it possible at all?
You can simply use the AAssetManager class in C++.
Basically you need to:
During the init of you library get a pointer on: AAssetManager* assetManager
Use it to read your file:
// Open your file
AAsset* file = AAssetManager_open(assetManager, filePath, AASSET_MODE_BUFFER);
// Get the file length
size_t fileLength = AAsset_getLength(file);
// Allocate memory to read your file
char* fileContent = new char[fileLength+1];
// Read your file
AAsset_read(file, fileContent, fileLength);
// For safety you can add a 0 terminating character at the end of your file ...
fileContent[fileLength] = '\0';
// Do whatever you want with the content of the file
// Free the memoery you allocated earlier
delete [] fileContent;
You can find the official ndk documentation here.
Edit:
To get the AAssetManager object:
In a native activity, you main function as a paramater android_app* app, you just need to get it here: app->activity->assetManager
If you have a Java activity, you need so send throught JNI an instance of the java object AssetManager and then use the function AAssetManager_fromJava()
Your assets are packaged into your apk, so you can't refer to them directly during runtime like in the sample code you provided. You have 2 options here:
Process the assets as an input stream, using
Context.getAssets().open('cacert.cert')
Copy out your asset to a local file in your files dir, and then reference the filename of the copied file.
Building off of the answer by #Sistr , I used getBuffer along with AASSET_MODE_BUFFER (instead of AAsset_read).
However, I was trying to write the buffer to an ofstream. I got signal crashes using the <<operator:
ofstream myStream(<some file>, ios_base::binary);
auto buffer = AAsset_getBuffer(asset);
myStream << buffer;
I presume this is because the buffer pointer points to the asset without a NULL character at the end (I was reading a text asset; Android source code). Using the write function worked:
ofstream myStream(<some file>, ios_base::binary);
auto buffer = AAsset_getBuffer(asset);
myStream.write((char *)buffer, AAsset_getLength(asset));
This is because the <<operator does not have to call strlen to find out how many characters to write since it is explicitly given by AAsset_getLength.
I have a question about Android programming. Basically, I am unsure of where to check where my file is, and if I wrote to it correctly. I want to locate where the file is, and I also want to know whether or not I wrote to it correctly. Below is the code I have come up with:
String lsNow = "testing";
try {
fos = openFileOutput("output.txt", Context.MODE_APPEND);
fos.write(lsNow.getBytes());
fos.close();
}
catch{
...
}
Where can I find output.txt? Might anyone know how to check this all out? if so, that would be great! I am using an emulator by the way. If I were to do this on a real Android, how would one approach this also? (Just for future reference)
You Test it in Two ways
Using File Explorer
Go to DDMS perspective--> Open File Explorer-->location of the file
Pragrammatically by using exits() method
File file = new File(context.getFilesDir(), filename);
if(file.exists())
Using openFileOutput(...) means the file will be written to internal storage on the Android device in an area which is secure from access by other apps.
If you want to make sure the file is written correctly then make sure your catch block handles any failures (if it is called then the file writing has failed).
To access the file once it has been written use openFileInput(...).
Good afternoon everyone,
I'm having a problem here with an CSV file that I wanna use to fill a dynamic table in Android.
I placed the file in the "data" folder of my emulator, and I did the following declaration to create my file variable:
file = new File("/data/Motors.csv");
I used a CSVReader class posted on another thread from this page (Link to the class) and also declared the following line to do the parse:
readerCSV = new CSVReader(new FileReader(file),';','"',0);
In the last line, the programmer to be able to create the variable has to send as parameters a Reader (Or a FileReader, it doesn't make a difference), the separator char, the quote char and the number of how many lines the CSV reader has to skip.
The problem comes that no matter in which directory (Not even in the root directory, which Java tells me that it's "/" through the file.getAbsolutePath(); method) it always gets to the point when the program throws the FileNotFoundException and I'm getting a bit frustrated because I have 2 days already with this problem.
If someone could please help me to get a bit of orientation of what I should do to get the file from the right directory... It would be a lot of help and I can go further with the code I have to finish.
Many thanks in advance!!!!
EDIT
I found a solution to open my file:
I have used 2 file variables: one gets the rout of the External Storage Directory (see first answer in the following link) and the other is declared as a new file, like the following lines in the code:
route = Environment.getExternalStorageDirectory();
file = new File(route,"Motors.csv");
Later I used again the CSV reader class that I found, where the first parameter is from the FileReader type (Sorry #Rajesh, but I couldn't use your alternative because you passed a FileDescription parameter from the AssetManager to the CSV reader class and then I had to change the whole class and that didn't help my problem at all).
Now I don't get the exception at all!!
There are various Storage Options in Android. Files can be stored in internal and external storages. If the CSV file is a static resource, you could think of bundling the file in the "assets" folder of your project.
If you are using the "assets" route, the following code segment can get you a CSVReader.
AssetManager am = getAssets();
AssetFileDescriptor afd = am.openFd ("Motors.csv");
FileDescriptor fd = afd.getFileDescriptor();
readerCSV = new CSVReader(fd, ';','"',0);
The above code snippet doesn't perform error/exception handling, please remember to take care of that. You need to copy the Motors.csv file to the "assets" folder within the project.
I'd like to know if it possible to read the content of file from SDCARD using JAVA API in Android.
I can do it using NDK C code by
int fd = open(str, O_RDWR | O_NONBLOCK | O_DIRECT);
readCount = read(fd, pBuffer, size);
when pBuffer is aligned buffer but when I read it using directly from Java using
bytesRead = fin.read(originalBuffer)
It brings file data from cache
So after long investigation and test I understand there is no way to open file directly from Java.
The only way to do it is to use NDK and open the file using O_DIRECT parameter as explained in the body of the question.
Note that in order to compile the code -D_GNU_SOURCE directive should be used.
I think that the main problem is to get a page aligned memory buffer in Java, in order to read the file, because passing the file descriptor with O_DIRECT is still possible through JNI ( http://www.kfu.com/~nsayer/Java/jni-filedesc.html - I did use this technique to be able to open file named with UTF-8 names on the Oracle Java VM for ARM which can't do that and this works).
But to fulfill your needs we still have to provide to the system a destination buffer for the read operation which is page aligned, because without it the underlying linux system gives you an EINVAL error after the first try to read data.
I'm not aware of any Java code which can provide page aligned read buffer.