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.
Related
By "permanent" I mean that it resists the application uninstall option that the Android OS offers. Obviously you cannot make a file not deletable in the user's terminal, at the very least, the user will always be able to delete it via the file manager if he wishes so.
I'd need this because in my app when some actions have been performed the app forbids from doing some more. So far this is controlled via a file, but there's nothing that prevents the user from uninstalling the app, and with a new fresh install this doesn't happen anymore.
I could implement some type of server-side logic to prevent the user from continueing but:
1) It's way easier to prevent just by checking the file.
2) It's not that important what happens if the user manages to bypass this security measure, so I don't really mind if a few of them are able to bypass the protection, as long as the file can be "permanent" and is in some obscure directory, not many users are going to be able to perform the mentioned behavior.
Is there any way to do this?
Just get the write file permission and write the file to the root file directory. As described here: https://developer.android.com/training/data-storage/files#WriteExternalStorage
After you request storage permissions and verify that storage is
available, you can save two different types of files:
Public files: Files that should be freely available to other apps and to the user. When the user uninstalls your app, these files should
remain available to the user. For example, photos captured by your app
or other downloaded files should be saved as public files.
Private files: Files that rightfully belong to your app and will be deleted when the user uninstalls your app. Although these files are
technically accessible by the user and other apps because they are on the external storage, they don't provide value to the user outside of your app.
this can be done by configuring auto-backup, assuming that the user has it enabled.
for example, here I've explained how to disable that behavior in debug mode.
the advance is, that it works across several devices, bound to the account.
instead of file , I would suggest to use following intent to catch uninstalling your app and put your logic to allow or deny for uninstall
ACTION_PACKAGE_REMOVED -: Broadcast Action: An existing application package has been removed from the device. The data contains the name of the package. The package that is being installed does not receive this Intent.
ACTION_PACKAGE_FULLY_REMOVED - : Broadcast Action: An existing application package has been completely removed from the device. The data contains the name of the package. This is like ACTION_PACKAGE_REMOVED, but only set when EXTRA_DATA_REMOVED is true and EXTRA_REPLACING is false of that broadcast.
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)
I have a requirement, wherein I have 4 android apps, which are sending notifications to a user, at a fixed time of the day. A user could have one, or more of these apps installed on his phone.
I want only one of the apps(any one) to show this notification to the user, because multiple apps popping up notifications is a bad user experience.
For this I need to share some data across the apps.
I was thinking of a mutex/lock based approach, the problem is, where do I store it?
Problems:
Shared Prefs: I don't know which app wrote the data first, and from which app's context should I read.
SQLite: Same Problem as above and app uninstalls need to be handled and SD card might be missing
Server: Mostly offline app, dont want to add internet permission just for this
I see files at a common location as the only way to store this information.
Is there any better way
As you said that the easiest ways is with file,
I did this before and i too wasn't able to find more easy way.
when you show the notification first time then Just make a new file anywhere which can be common for any app and then check if file is exist.
if it exist then don't show the notification and if not then show and make file again, also remember to delete the file from any of your app when day changed, use AlarmManager for this.
hope it helps.
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
To preface my question, couple things to note. I don't want to store said file on the sdcard in this case. The file also cannot be storage directly in the apps local files directory. It needs to be in a subdirectory, so it cannot write the file using openFileOutput() and MODE_WORLD_READABLE.
The app may download files small files like pdfs and store them locally in a subdirectory. I would like to be able to have the user open these files if they have an app that can open them.
For example here is an intent for sending a pdf:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(path), "application/pdf");
startActivity(intent);
path being something like: /data/data/packagename/files/subdir/example.pdf
That intent will open a pdf viewer, but the viewer is unable to open the file. I assume this is a permissions issue. I tried Mark Murphy's suggestion here: http://groups.google.com/group/android-developers/browse_thread/thread/4e55d869213483a9/b7270078ac1a2744?lnk=raot of using Runtime.getRuntime().exec("chmod 755 " + fileName); but it didn't make any difference. He also suggested a Content Provider but I would like to avoid it if I can because it seems like a lot just to get this file over to another app.
If the content provider is the only option, do I have to save the file to the content provider or can I just use the content provider as a pass through to get it to the other app when I need to?
Thanks, let me know if I'm not being clear.
I also tried all the options you mentioned (and more) and a content provider was the only way that worked for me. I'm not exactly sure what you mean by "save the file to the content provider", but you don't actually need anything in a database for the provider to serve up the file to the other application.
You might like to look at the android:sharedUserId manifest property:
The name of a Linux user ID that will be shared with other
applications. By default, Android assigns each application its own
unique user ID. However, if this attribute is set to the same value
for two or more applications, they will all share the same ID —
provided that they are also signed by the same certificate.
Application with the same user ID can access each other's data and, if
desired, run in the same process.
Be aware that your applications already have a default one that you can't determine (AFAIK). It may be as well to define the same sharedUserId for both apps, then install them on a new emulator.
As a second point, are you sure that you will be able to view a PDF file? I thought that there was no support for it in Android yet.