Android NDK internalDataPath - Writing to file - android

I'm using internalDataPath within my NativeActivity which when accessed at runtime looks something like this:
"/data/data/app.name/files"
I then try writing to the file like so:
- fopen("/data/data/app.name/files/test.txt", "wb");
- fwrite(buffer, size, count, m_handle);
- fclose(m_handle);
In this case, the fopen will fail and won't open the file which realistically means the other functions don't get called, I experimented by looking at the file system and instead, tried the following path.
"/Android/data/app.name/files/test.txt"
This works, it creates the file and allows for the other functions to write and close the file.
My question is, how come internalDataPath starts with /data/ instead of /Android/? Have I done something wrong in the setup of my application? Should I be calling a different function?
It's also worth mentioning that
externalDataPath = "/storage/emulated/0/Android/data/app.name/files"
Which means that for this device (which doesn't have an external SD) it points to the correct INTERNAL files path.
Let me know if any of this is unclear or you require more information.
Thanks

I added mkdir() to ensure the entire internalDataPath tree is definitely created and it seems to have worked on my Nexus 7, I can see the files being created with ES File Explorer.
It also works on my Galaxy S6, however I can't actually see the files in the ES File Explorer, but it works because the file is loaded and read upon the next restart so I can only assume I can't see the file because this device is not rooted.
It's worth noting that between versions of Android, internalData path has changed location, for example:
Nexus 7 (5.1.1):
internalDataPath = /data/data/app.name/files
Galaxy S6 (6.0.1):
internalDataPath = /data/user/0/app.name/files
These paths are absolute, or at least relative to the highest view-able root directory in ES File Explorer.
Not sure if this will help anybody, the main part of the problem was probably my own lack of knowledge of the Android file system since there seems to be lots of similarly structured directories, it's easy to get lost down the wrong one.
Thanks to Patrik and Dave for spending time looking into it with me.

Related

Can't boot Android device after replacing system.img

I am working on a custom android device using the i.MX53 board from NXP (formerly Freescale). I have the OS source code, various intermediate files, and the final resulting files once produced by another developer (who customized the OS, but has since left our company). I now need to modify the contents of the system partition on these devices. I have attempted to build and load a new system.img file using make_ext4fs.exe and the directory which contains the original collection of files the prior developer must have used. I believe I have created a nearly identical system image, as the one previously used. They are both ext4, 200MB.
There is a utility for this board (called MfgTool) which copies and mounts images automatically for you at the click of a button. That MfgTool successfully writes my image to the device. When I try to boot, however, it fails and just loops with the custom boot image being displayed. If I swap out the new system image and restore the prior one in this process, everything works again. So it has to simply be a matter of getting this system image built correctly.
What might be the cause? What difference in the images might cause this? Is it possible there is a signature needed, or some other kind of protection which I'm failing to account for?
Replace one of the system image service executable with a shell that dump kmsg and logcat to a file (in data partition or external storage for example) and then call the original executable. Then, boot to your previous system and collect those logs.
It turned out that my primary problem was that I need to set the mount point for the image to "system" NOT "/system" when it was created via make_ext4fs despite all documentation out there to the contrary! I figured this out by carefully reading the ASOP source: ...build\tools\releasetools\img_from_target_files.
Of note, after this hurdle, I ran it another problem where the device was acting funky. That turned out to be the result of not having any symbolic links in the image. It seems like at the least you normally have symbolic links directing your "bash" commands to the toolbox binary in system/bin. I don't know how you normally get those, but creating those links and then bundling them into the image fixed that. I suggest checking the bin directory for symbolic links if you manually create a system image like this.

Corrupted data read from mounted obb file on Nexus devices

We have a cross platform mobile app that uses a native C library to read some data (among other things). On Android the data is in a obb file that we get using the Expansion APK mechanism. This has been working very well for us. However, we've found that on the 2nd generation (2013) Nexus 7 table and on Nexus 5 phones, we are reading some data from the obb that is corrupted. The actual obb file is not corrupted, but what we read from it is.
The best example I have is with WebView reading an HTML file from the mounted obb. The first part of the HTML will be fine and then there is gibberish in the second part. Interestingly, the gibberish is recognizable as binary data from elsewhere in the obb. It is almost like the Android code that reads the obb is getting the block mapping wrong.
I've narrowed it down to being triggered by some C code that reads objects out of the obb. If I comment this out, the HTML will be fine when I later access it. Now it is possible there are bugs in the C code, but this library has been used on two other platforms without issues. It also works just fine on a first generation Nexus 7 and on other non-Nexus devices.
So does anyone have any thoughts about what this could be? It seems to happen with both Android 4.3.x and Android 4.4.x on these Nexus devices. What could be different hardware-wise that could cause this corruption? I assume things like the C library come with Android and aren't built into the firmware somehow?
I had the exact same problem, randomly corrupted assets when reading from the OBB in a native C library using stdio functions. Segments of 128 bytes were consistently corrupted in the mounted OBB. Any changes in the data would shift the byte segment, resulting in a different asset being corrupted. This was only a problem for phones running O/S v.4.4.x(KitKat) and v.5.x.x(Lollipop), phones running 6.x.x(Marshmallow) and later are unaffected as far as I know.
To circumvent this, rather than mounting the .obb, I ended up using the alternate .zip method as outlined here: https://developer.android.com/google/play/expansion-files.html.
I simply packed the data into a .zip with 0 compression(store), renamed to .obb, uploaded it to google play. When the user first starts the app, I extract the file to external storage using the APK Expansion Zip Library and then read the files directly rather than via mounting. This results in the app being twice the size on the phone, but it's preferable to being completely broken on some systems due to corrupted data.

Android SD card writing fails, but not consistently

I've got a pretty thorny problem with Android 2.3: I have an app that gathers various logs for debugging and support purposes (my company does Linux for rugged hardware), and has stopped working lately, because it's failing to write to the SD card. Here are the symptoms I've seen and the investigations I've carried out:
Happens across multiple devices of multiple types with different SD cards, all of which have been checked for filesystem corruption (no issues found).
All devices report: Environment.getExternalStorageState() equals Environment.MEDIA_MOUNTED.
All devices also report that Environment.getExternalStorageDirectory().getAbsolutePath().canWrite() is false.
Via PackageManager.checkPermission(), my app reports that it has the WRITE_EXTERNAL_STORAGE permission.
OI File Manager is able to create directories and move files on the SD card; my app can do neither.
This code is sufficient to cause a failure:
String sdcardDirectory = Environment.getExternalStorageDirectory().getAbsolutePath();
File directory = new File(sdcardDirectory + "/logger");
if(!directory.mkdirs()){
//fails here.
Log.w("Logger", "Could not create logger directory.");
}
Since I have access to the keys for this device, I even went so far as to sign the app with the platform key and run it as android.uid.system, with no luck. Anyone have any ideas?
It turns out this is a case partly of bad diagnosis on my part, and partly an apparent change in 2.1 to 2.3.
The bad diagnosis was that the directory above was indeed being created. The apparent change between 2.1 and 2.3 may be Android internally, or it may be the way we're setting up paths, PATH, and symbolic links in our own builds. Further down from the code in the original post, there are a few calls to exec() to get e.g. output from logcat and copies of various bits of useful information in /proc; using absolute paths to the commands fixed the problem.
Thanks for the help in ruling things out.

Packaging Flash Builder Apps for Android/IOS - assets directory Q

First timer here.
I've been writing an app that's intended to be deployed onto mobile platforms (iOS and Android ). This uses Flash Builder 4.6's android build target - it uses a subdirectory in the /assets/ directory, that contains an arbitrary number of .png files.
I code a directory loader as such:
public function LoadFromDirectory(directoryName:String, store:Vector.<BitmapData>):Boolean
{
//Changed here: this should work on both the development environment, AND the device.
//Guess what...
imageDirectory = File.applicationDirectory.resolvePath("assets/" +directoryString);
//This is triggering on Android. Doesn't do so in ADL. Not tested on iOS yet,
//but come on, if it doesn't work here, it won't work on iOS...
if (!imageDirectory.isDirectory)
{
trace("Directory not found:" +imageDirectory.url);
return false;
}
/*Snip loop through the contents of this directory, loading anything that is
a PNG and storing the bitmapData of all loaded PNGs into the vector, one by one*/
/*This of course, ALL works in ADL*/
}
This works in the air virtual devices, but isn't working on the mobile devices or on deployment. This is where I'm stuck.
Edit: Ok, I've gone and reduced the File code to just one line. I should be using resolvePath for cross-platform compatibility; also, the packager from Flash Builder doesn't see the "assets\" subdirectory unless I put it inside "bin-debug\", because that's where the compiled SWF went.
Still doesn't solve the problem tho - at least for the Android build, I can see the assets folder in the apk (by renaming it to a .zip and extracting it all), and it's the correct one (alongside the app's XML files and the SWF).
The apk installs and runs, but isDirectory still returns false when I debug on the device itself (once again, not on ADL - on the device only). Commenting that entire if...segment will crash the app instead because well, it can't find the assets\ directory.
I'm this close to solving the problem; would appreciate if someone helped me with the final step, because it's taking bloody ages to figure out.
PS: I would love to simply just embed the images in a FLA or SWC which I've done before and it works. Unfortunately, the number and name of images in that particular directory is arbitrary; the only thing that I'm certain of is the supported extensions.
PPS: Usage of this function: LoadImagesFromDirectory("imagesdirectory"), which should look under app:/assets/imagesdirectory in any platform. The Boolean return is for debugging (returns false if a directory with that name doesn't exist.)
...alright, I don't know if this is documented, but apparently I was calling LoadImagesFromDirectory to a directory name that is all caps, because on the PC, the target directory was also in all caps.
So in the test platform, the directory resolved to "app:/assets/IMAGESDIRECTORY".
But upon export, the device showed the directory instead resolved to "app:/assets/Imagesdirectory", therefore making the call to IMAGESDIRECTORY invalid.
Oddly, looking for "Imagesdirectory" works for both the PC and the device without changing folder layout and names.
Looks like I've been Gotcha'd - remember never to give directories names in all caps...

Android file storage options / conventions

So I'm making this android application, that needs to read data from user-provided CSV files.
The CSV files are more confortably edited on a desktop computer, so I have no editor in the app, which is 'read-only' ; I assume there is a file on the phone's SD card.
Following the Data Storage documentation, I managed to write a dumb version that reads the file from external storage, hard coding the folder location relative to whetever getExternalStorageDirectory returns. So for the moment I have :
private static final String CSV_FILE = "/Android/foo/bar.csv"
...
File f = new File(Environment.getExternalStorageDirectory(), CSV_FILE);
Then I would connect my phone to a PC, create a "foo" folder in the "/Android" folder (that exists on my phone), copy the "bar.csv" file, and everythings goes fine.
Now obviously, this is not acceptable if I want to distribute the application. So I have a few questions :
The natural solution is to softcode the file location, and in any other system I would rely on a built-in "file manager" or something, to let the user browse to the right file.
Surprisingly I could not find such a control, and it seems like there are lots of third-party File Browser app. Does it mean it is not "customary" to ask a user to choose a file on their phone ? Should I write my own 'file browser' ?
Are there conventions about how I should name my "foo" dir ? I've seen apps creating dir with a name that looks like a java package, am I mistaking it with internal storage ?
There is also a getExternalStoragePublicDirectory method that takes a "directory type' constants. In my situation, would it make 'sense' to assume the file is in DIRECTORY_DOWNLOADS ? (or in some subfolder of DIRECTORY_DOWNLOADS ?)
Should I bother about how a lambda user will put a file on their phone ? To me plugging the phone on my PC is simple enough, but is that really easy on all droids ?
Sorry if all of that sounds trivial, just trying to clear my mind before doing something stupid.
Thanks.
Does it mean it is not "customary" to ask a user to choose a file on their phone ?
Correct. Android, like iOS, tries to get away from "files" as much as possible.
Should I write my own 'file browser' ?
There are certainly plenty of third-party applications for file browsing, some of which support ACTION_PICK or similar operations (e.g., OI File Manager). I will be surprised if nobody has written a reusable component for this.
Are there conventions about how I should name my "foo" dir ? I've seen apps creating dir with a name that looks like a java package, am I mistaking it with internal storage ?
No, you are probably seeing the results of getExternalFilesDir(). If you are only supporting API Level 8 or higher, I'd just use that. If you are supporting earlier versions of Android, you might consider finding out the appropriate directory for your app that would be used via getExternalFilesDir() and use that "manually" for older Android versions.
There is also a getExternalStoragePublicDirectory method that takes a "directory type' constants. In my situation, would it make 'sense' to assume the file is in DIRECTORY_DOWNLOADS ? (or in some subfolder of DIRECTORY_DOWNLOADS ?)
That is for downloads -- more accurately, things the user downloaded that they want to hang onto independent of any installed app. It does not sound like this fits your scenario.
Should I bother about how a lambda user will put a file on their phone ?
What is a "lambda user"? To quote the Bard, "but, for mine own part, it was Greek to me" :-)
To me plugging the phone on my PC is simple enough, but is that really easy on all droids ?
It is somewhat more painful on Android 3.x and higher, as Android moves away from USB Mass Storage mode (think USB thumb drives) and to MTP (think MP3 player) for its USB file transfer protocol. While this has overall benefits, it is annoying for OS X and Linux users, as neither have built-in MTP support. Also, it assumes the user has a USB cable handy. Your overall setup also assumes the user has a desktop OS handy.
Nowadays, more developers would probably go the route of creating a Web app rather than a desktop app, and syncing the data to the device over the Internet. This eliminates the need for fussing with cables and does not tie the user to one specific "desktop" machine for data entry. It does, however, require Internet access, which may or may not be suitable for your situation.

Categories

Resources