Accessing Android USB Mass Storage Using Delphi - android

I am trying to write an Android App in Delphi 10.4 (primarily for AndroidTV) using Delphi which can read or write files from/to USB mass storage. I can see the files using FileManager App, but have failed to see them with my App. I found a library on GitHub (Libaums) which would appear to do all I want and much more, but is written in a mixture of Kotlin, Java, and C, which would appear to be very difficult to integrate with Delphi.
Edit: The paths I have tried include: GetDataDirectory(), GetRootDirectory(), GetExternalStorageDirectory(),GetSysExternalStorageDirectory(), GetExternalStoragePublicDirectory(), /mnt/usb001, /mnt/usb002, /mnt/androidwritable, /mnt/user.
The device in mind currently uses SDK 28, but I would like a solution that would still work on later versions.
All my attempts to get file paths report non-existent, which I take to mean I have a permissions problem. Can anyone:
(1) Advise which file path to request?
(2) How to obtain the relevant permissions?
TIA

Related

Repeatedly save to external storage on Android in Xamarin Forms

I am running into an issue in a Xamarin Forms project I am working on, building and using on UWP and Android (don't care about iOS currently). My app is one which connects to a Bluetooth device to record data, stores it within the app, and exports the data into a .txt file or similar that is used for other purposes outside the app. On Android, targeting either Android 11 or Android 12.
I am working with Xamarin 17.4.0.301, Visual Studio 17.4.0, and .NET Framework 4.8.04084, and Xamarin.Android SDK 13.1.0.1.
My issue is trying to save to a file repeatedly that is accessible. Currently, I use a file hidden in the app's internal storage, using a filepath like this:
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "data.txt");
This of course works on both UWP and Android; however, since it is internal, it cannot be accessed by a file explorer on Android. To be seen on Android, I have to export it from the app into a file explorer app, using code like this, where the command is tied to a button press:
OnShareDataCommand = new Command(ShareDataButtonClick);
...
private async void ShareDataButtonClick() {
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "data.txt");
await Share.RequestAsync(new ShareFileRequest {
Title = "Share Data",
File = new ShareFile(fileName)
});
}
This requires a user to press the button to export. My desire is for the system to automatically make a file somewhere accessible in the file explorer (like a Downloads folder) and continuously save to it when the function is called. To do this, I have enable access to external storage as such in the Android Manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
But I am running into issues accessing it. The first is when I try to create a filepath that is in external storage like this, based on this StackOverflow question:
var fullPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "file_name.txt");
When I do this, it says Android is not in the context. I imagine this is because I am in Xamarin Forms building for multiple platforms. How can I fix this? How can I access Android's External Storage while in Xamarin Forms? Can I make a platform specific function, and if so, how do I go about it?
This Xamarin forums solution did not work.
I have tried using this line from the External Storage for Xamarin.Android guide, which also does not work because it says Environment does not have the method used:
Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDocuments).AbsolutePath
Any advice? I do not want to make it an Android specific app, as I need the UWP functionality, but I could make a platform-specific save function.
Since Android 11 Read/Write External storage is not allowed, the permission will not be granted. Unless you have an app like a file explorer and even then you have to apply to Google before it will be accepted. So you need to forget about writing to external storage.
See the following links
https://medium.com/swlh/sample-for-android-storage-access-framework-aka-scoped-storage-for-basic-use-cases-3ee4fee404fc
https://www.zoftino.com/how-to-create-browse-files-option-in-android
https://mateuszteteruk.pl/how-to-use-android-storage-access-framework-with-example
https://thedroidlady.com/2020-08-24-android-scoped-storage-demystified
I did it with my app back when I released for Android 11.
If you need any further help just reply here. I should add, I only write Android apps, so I can't help out with anything Forms related or UWP
#ToolmakeSteve, Is your question addressed to me? I'm writing in C# and Xamarin.Android. I don't think a couple of code snippets would provide anything useful. Just follow the links and the link you posted. I'll attempt to provide a test app, but I've not enough time to do that at the moment.

How to get full access to files in external storage Android 11?

In Android 11, the getExternalStorageDirectory method that returns the path to external memory is deprecated. Instead, new APIs appeared for working with specific public folders or application folder.
But for a work task, I need to work with folders and files located at the root of external memory. I haven't found an example of a new API that allows this. In the Google documentation, in fact, only how to get permission (via ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION) is not a problem. In addition to working with files from Kotlin, I also need to interact with files from C++. There are no problems with the deprecated API, there you can get full paths to files and do whatever you want with them. But what about the new APIs? Or just use the old API, hoping that it won't be released in the next versions?
PS The application will not go to the market, so I can get any permissions and do whatever I want :)

Opening Files from a String Path with Android NDK

I've been going over the Android file access documentation lately, but I seem to be unable to figure out how to actually open a file given as a string containing the path to the file I'd like to open.
What I (eventually) want to accomplish is something like this:
The user selects a specific kind of text file using Intents, receiving a URI to the file. From this I derive the path (getPath()) and pass this string to the native C++ code.
The native C++ opens the file from the string, parsing the content.
Perform some actual work with the above.
From what I've found so far, it seems like it is no longer possible to open files this way (as of SDK version 26 at least):
A hard-coded path to a file I know exists gives me permission denied.
The path itself received from getPath() triggers a No such file or directory error.
One workaround called for opening the file on the Java side using the ContentResolver, and then passing the file descriptor to the native side. This works, but it's problematic: the files can contain references to other files to be opened ("include files") making such a solution of limited use.
Just to make things clear, these files reside locally on the "USB" partition of the Android system, unrelated to the app itself. Not as resources/assets to the APK or anything similar which other questions of this kind seem to require.
In summary, I guess the question is this: Is it possible to open a file, and possibly any other files it refers to, given a path from the Java side of the application? Is there any requirements for doing this, such as requesting the correct permissions for folders or something similar?
As of Android 6.0 (API level 23) you need to request permissions every time your app starts for "dangerous actions" such as accessing the filesystem or reading contacts. The linked pages already have a snippet of code you can copy.
On older phones requesting permissions in the manifest was sufficient, but the target SDK version was recenly upped to 8.0 (=26). If you want to support devices pre-6.0, the Android compatibility library will allow you to call the same API.

Understanding the Apache Cordova Filesystem for Android

I fully read the documentation of Cordova plugin filesystem. Furthermoe I've been googling without though conclusive explanations.
Particularly, how do the paths stored in the variables in cordova.file.* map the real folders in Android filesystem that you can see on any File Explorer? For example, I cannot save a file into the Downloads folder. I tried file:///android_asset/Download without success.
What exactly is the protocol file:/// and the path file:///android_asset/? What is the "application's sandbox"?
For example, I save a file into cordova.file.cacheDirectory because I need to deal with a temporary file, but I tried to find such file within a file explorer, and I can't find such file. Is it hidden somehow? I can't find it neither in /data/data/<app-id>/cache nor in "file:///data/user/0/com.form.parking.violation/cache/" (real value of that string).
I know, it's too many questions, but I will plan to make this a canonical question, since clear and pedagogical information is very scarce.
Using a 'File Manager' app on device won't give you access to items listed as 'Private' in the documentation you've listed. 'Private' means no other app should be able to see the contents which is sort-of described by "application sandbox". Normally a sandbox is for describing an environment which something can't get out of. If you aren't familiar with multi-user environments it can also mean that others without the right level of permission can't see in.
And unless the device you are testing on is rooted, you won't be able to see those 'private' files like the SQLite database and other files you are interested in unless you use adb from the Android SDK with the adb shell command run-as as described here:
Android ADB access to application databases without root
Note that to grab the files you need to have your Cordova app debuggable by Android Studio (debug mode).
For what is file:///android_asset/ I'll refer to this SO question:
What does file:///android_asset/www/index.html mean?

How to transfer txt data file from Android app to Windows

I have an Android application that generates some data (simple text file) that I would like to transfer to my PC for further processing. My understanding is that my storage options for a place to save such a file are a) internal storage or b) external storage. My device is a rooted Nexus 7 running Marshmallow, and I can't get either option to work.
With internal storage I'm able to write the file but then it's nowhere to be found using ADB or Eclipse DDMS. With external storage I'm getting FileNotFoundExceptions which I'm guessing are due to new complicated permissions, so none of Android saving file to external storage is working.
Is this possible and, if so, is there an easy way to do it?
What is your targetSdkVersion? If you target 22 and below, the new permission policy won't take effect.
It is possible to write a text file in Android and read the same in your PC using external-storage.
This app does the same.
You can find a simple example here.
If this does not work for you, kindly share your code-snippet that writes the file.

Categories

Resources