Saving file using Storage Access Framework in Android - android

I am integrating the Document Access Framework with my cloud storage access app.
Using this documentation I have been able to access the file and retrieve it (I simply use Gmail app's attach function to check this).
I am now trying to find how to save file using the same method (Save file directly via the app to cloud storage) and I have done the following changes:
For the getRoots call,
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE);
and I have also overriden the createDocument method.
I don't see much in ways of sample code or documentation on how to do this. I also see that a bunch of apps like the "Photos" app have "Share" button that use a different method (The logs show miniShareActivity) and my app does not show up in that (It looks like it is using a different filesharing mechanism)
I am looking for information on
How to use the SAF to store file (any sample file will be great or pointers to documentation). I Am assuming it will allow the user to use the picker interface to navigate to folder and store the file.
How to get the app to show up in the "Minishare activity" list of apps to import the file into the app (It looks like it does not provide a picker interface but I still would like to provide the support so the file is saved to a default location)

The Share button you're referring to in other apps probably uses ACTION_SEND as the Intent action, rather than ACTION_CREATE_DOCUMENT that was introduced with the Storage Access Framework.
You probably want to support both, since ACTION_CREATE_DOCUMENT was only introduced in KitKat and older apps may not be aware of it. Similarly, you may want to also support Intent action ACTION_GET_CONTENT for read access on pre-KitKat devices (ACTION_GET_CONTENT is handled by the SAF when running on KitKat+, but your app still needs to handle it when running on a pre-KitKat device). Are the <intent-filter>s in your AndroidManifest set up to match all of those Intent types?

Related

What is com.android.externalstorage?

Despite this being a simple question I cannot find the answer on google or stackoverflow.
When I use the following code I get this result //com.android.externalstorage.documents/tree/primary:Podcasts
var intent = new Intent(Intent.ActionOpenDocumentTree);
intent.PutExtra("android.content.extra.SHOW_ADVANCED", true);
intent.PutExtra("android.content.extra.FANCY", true);
intent.PutExtra("android.content.extra.SHOW_FILESIZE", true);
Can you help me understand the parts of my result?
How Android Storage works?
To ensure security between Android apps, Android didn't let you directly access every file within the storage system. They have something called ContentProvider.
Think of this content provider like a waiter, that your apps can ask for a certain file/folder (through Content Uri).
Content Uri will look like this: content://[Authority]/[path]/[id] is just an example of Content Uri. com.android.externalstorage.documents is an example of authority (for access to External Storage providers).
So in your case, your Uri will gain you access to the directory of Podcasts in your External Storage.
By having Uri, you can communicate between apps or service provider easily without having to pass real file every time you ask or give one. Just pass a lightweight simple Uri.
What happened in your code?
If you're wondering what happens in your code, try to look at the Reference.
It says:
Allow the user to pick a directory subtree. When invoked, the system will display the various DocumentsProvider instances installed on the device, letting the user navigate through them. Apps can fully manage documents within the returned directory.
I'm not sure what you're trying to achieve (please clarify if you can, so I can help out), but I hope my answer contains enough information.

Xamarin.Forms app need to write to a shared local storage location

I am in the process of writing a Xamarin.Forms line-of-business application.
The app will be targeting UWP and Android.
I have a requirement of being able to store information and pictures taken, in a shared folder on the local storage. This way, multiple users of the same device at different times can resume work-in-progress of the first user.
I am not sure what my options are, as I am unable to write outside of AppData folder (for UWP).
I read about potentially using a Picker and storing the selected folder in the FutureAccessList for UWP, but I am unsure if it will actually work and seems hacky as I will need to come up with a way of doing the same for Android at a later time.
Any ideas/pointers are greatly appreciated!
There is a special ApplicationData.SharedLocalFolder folder that allows you to share app data across user accounts on a PC. Its main limitation is that it requires appropriate Group Policy:
SharedLocalFolder is only available if the device has the appropriate group policy. If the group policy is not enabled, the device administrator must enable it. From Local Group Policy Editor, navigate to Computer Configuration\Administrative Templates\Windows Components\App Package Deployment, then change the setting "Allow a Windows app to share application data between users" to "Enabled."
I feel that the fact that this is not allowed by default is a great obstacle to the usefulness of this API.
There a publisher cache folder, but this solution is not appropriate for you because of documentation says:
Publisher Cache shares data across apps for the current user
So I would probably really go with the picker-based solution you proposed. Offer the user to select a folder to save the data to using the FolderPicker and then store the selected folder to the FutureAccessList. The future access list is reliable and can even track the changes of the selected item (like when the user moves it to a different location). The abstraction of the selection process in a cross-platform manner may be a bit more complicated, but it should be possible to hide it behind a dependency service implementation. My guess will provide an async method that will initialize the target location. On UWP this will check the FutureAccessList if a location was selected previously and if it was not, it will use the FolderPicker to let the user select it and will store it for future user afterward. On Android, it will work in Android specific manner (I am not sure what are the options there). Then the service will have some file manipulation methods that will abstract the platform-specific manipulation with the folder (I think you cannot use the common System.IO namespace, as you cannot directly access the user selected folder outside of the StorageFolder API)

In Android, how to add a file to another application

I need to place a file inside of another application's specific folder. Is there a best practice, or related expected behavior for this?
To solve the issue, I have created the desired file during my APK's installation, then written its contents. While this works (since I have root rights), I want to know if is there a way to "request" another application to "create the file themself", this is mostly to guarantee that when that other application is removed, that it removes its files (since my app is the owner of that file).
I am unsure if this is considered good behavior, and could not "phrase" the question in a way that showed related results (I am not an native English speaker).
I need to place a file, inside of another applications specific folder
If by "applications specific folder", you mean internal storage, this is not possible, except perhaps on rooted devices.
I want to know if is there a way to "request" another application to "create the file themselfs"
Not in general. Some developers might have an API for this in their apps.
The official way of sharing data between apps is ContentProviders.
There is no limit to what may back the specific provider - a file, database or some other data source. I think this is the best way to go in your situation.
The approach you have described is indeed strongly advised against. The whole Android security is based on the idea that you can't directly access the data of other apps.
Ok, here is my proposal. I will assume that you can add functionality to the server app or define some technical guidelines for it at least, so that it's developers have to add the functionality.
A - Server App
B - Client App
[B] Create the html file in the common storage
[B] Save its location to some String variable
(Optional) [A] If there are more server apps that the user can choose from, make sure they all have a BroadcastReceiver with a common INTENT_ACTION.
[B] Send a broadcast Intent with the path saved in 2. as an extra value.
[A] Receive the Intent, check if the path in the extra is present.
[A] Get the file from the received path and copy it into the internal storage.
(Optional) [A] Add a BroadcastReceiver to monitor app uninstalls. When notified about the client app being uninstalled, remove the html file you received from it.
This is the basic algorithm, but I guess the implementation is obvious enough. Let me know if it solves your problem.

Can android intent be used to access phone directory?

I am making an android app to open a file and send it back to a remote server. I know how to do this with a file hardcoded into the app but I want to make it so that it can search the phone's directory, choose a file then send it. I am wondering can this be done with an intent? Or is there any other approach that could be used?
Yes, you can do this with an Intent. You would use startActivityForResult() and specify an Intent that can launch a file picker. Now the actual Intent you use depends on which application(s) you expect will actually service this Intent for you. For example, ES File Explorer exports a custom PICK_FILE action that you can use to support a file picker. With any scenario where you rely on a third party application to provide a service, you'll want some sort of fallback in case no application can handle the Intent (such as linking to an app that implements the Intent in the Google Play store). A similar question may provide some additional Intents to try for a variety of different file choosers available.

Android application's exposed API or hooks

What is the best way to discover an Android application's API or hooks into/from the application?
Specifically, I am looking to pass a parameter or data to an application, utilize the application's specific functions, and return data or a parameter to the calling application.
A few ideas come to mind, but I am unfamiliar with what is available, specifically to Android.
Contact an application's developer directly
Somehow decompile the APK to browse the source
Read any available documentation
Some ways to check out what is available for :
Tool to re-engineer closed APK files
http://code.google.com/p/android-apktool/
Review intent filters for actions
Lookup the app in some sort of application manager on your phone. Android System Info. If you go to the details of the app it will tell you where the apk is and the name of it. For instance, under the Email app you can see "Source: /system/app/Email.apk".
To pull that off just do "adb pull /system/app/Email.apk Email.apk", to pull it to your current directory.
Look at the Manifest.xml. Rename the apk to zip and unpack.
Follow the instructions here: http://android.amberfog.com/?p=582
Then you can read the decompiled Manifest.xml and look at the intent filters they are registering.
Android applications are all in their own sandbox, so you can not just arbitrarily call some other Android applications' functions, they would need to be made public to you somehow.
If you are looking to execute some function that is provided by another Android application, you would most likely need to hear about it from the developer, most likely from their public documentation if they have any.
The correct way to do this is to use "intents". With an intent, you can launch another application (such as a barcode scanner) and the user interacts with it. Then, the application exits returning some data (such as the barcode). Try googling or see:
http://www.vogella.com/articles/AndroidIntent/article.html

Categories

Resources