Creating a file on an Android device - android

I am new to Android development using eclipse, although not new to software development in general.
For my first real project, I am trying to modify the example SoftKeyboard that is supplied with the SDK. I want to modify one of the keys to act as a function key, when followed by a single letter key it will enter a canned string - performing a macro function.
So far so good. I have the key and graphics modified, and found where to respond. I would like to put the canned strings in an editable Properties file stored where the keyboard can find them.
That is where I'm having trouble. It seems that I can't to create and save a file. I don't know if it's read/write permission problem, whether the keyboard (it runs as a service) is not allowed to create a file, or my code is just plain wrong.
Can someone help me out – point me in the right direction?
Thank you very much.
Barry.

If these are canned files that come with the APK you install to the device and only need to read (not write), you can place them in the assets folder of your project. Then use the resource manager to load them:
Resources resources = getResources();
InputStream moduleSearchTemplateIn = resources.getAssets().open("file/name/here.properties");
If you want to read/write files on the SD card, you'll need to add a permission to your manifest. Though, for this purpose, I'd probably prefer a SQLite table.

Related

Getting root directory contents

I have an app with data stored (by previous developer) in user-based directories: context.getDir(userLoginHash, Context.MODE_PRIVATE). And there is no users list - when user logs in app tries to load contents of his directory (or creates new one), when user logs out directory remains on the device.
And now I wan't to clean the data. So I need to get list of such folders, but didn't find method for that. It confused me a lot because task looks too obvious. Do I miss something? How can I do this?
So I need to get list of such folders, but didn't find method for that
There is nothing really built-in for that.
How can I do this?
Start with:
File motherOfAllUserDirectoriesAndOtherStuff = getDir("whatever", Context.MODE_PRIVATE).getParentFile();
You can iterate over all of the contents of motherOfAllUserDirectoriesAndOtherStuff using standard Java I/O (e.g., listFiles()). However, bear in mind that not everything in motherOfAllUserDirectoriesAndOtherStuff will be your user directories. SharedPreferences, databases, other files, etc. will also be in there. You will need to devise an algorithm that can determine whether a subdirectory of motherOfAllUserDirectoriesAndOtherStuff is one of your user directories or not, perhaps based on what a hash looks like.
If you can someday rewrite this, create your own root and put the user directories in there. IOW:
File userDir = new File(getDir("myAppRoot", Context.MODE_PRIVATE), userLoginHash);

How to extend app with downloadable APKs (plugin sort of)

I'm just wondering how the following scenario can be solved:
I want to write a very simple app for my daughter. The app displays 4 colored fields on the activity and through speech output says something like "tap green". She should then tap the green field to get positive feedback. So far, so easy.
I then thought it might be nice if the app would also "grow" as she grows older. Maybe later I want to have a game mode where I display animals, numbers, vehicles, etc., so it would be nice if I could have something like "Shape sets" - basically a set of images along with a description of what the app should say for each image. Also easy enough - all you need is a set of images and an XML file describing the images.
BUT
I'd like to be able to install these "Shape sets" as additional APKs later on, so that I don't have to modify the app every time. I'd like to install the APKs, so that the contents are added to a specific sub folder on the SD card, into which my app looks to enumerate available "Shape sets".
If I ever published the app to the Play Store, other people should also be able to download the "Shape sets" I create (no need for user contributions, though).
Is that possible? If so, what would I have to do to have the Android OS "copy" the contents of an APK to a specific folder (lets say "/TapGame/Shape Sets/Animals") on the SD card? Or is there even another way of achieving what I want that I didn't think of?
The term "plugin architecture" just came to my mind as I wrote the question. Searching using that term I found this question: Extend my android app in different APK
It seems to provide a solution to my problem - I'll investigate this further, but please feel free to suggest other possible solutions!
Is that possible?
Um, sure.
If so, what would I have to do to have the Android OS "copy" the contents of an APK to a specific folder (lets say "/TapGame/Shape Sets/Animals") on the SD card?
Android won't do any of that. You have to do that. You would have to detect that a "shape set" APK was installed (either watching for package-installed broadcasts, scanning all installed apps for ones that seem to be a "shape set", etc.). Then you would have to arrange to copy whatever you wanted to wherever you wanted it, either by:
Asking the "shape set" app to do it (e.g., send a command to some IntentService), or
Using createPackageContext() and trying to do the copying from your main app
Or is there even another way of achieving what I want that I didn't think of?
Um, just use ZIP files that your app downloads itself from a well-known location. That corresponds to Dave Smith's final paragraph of his answer on the question you just linked to in your edit.
Or, just update the main app. I'm not quite certain what effort you think that you are saving otherwise.
Or, just keep the content online, using a Web service to indicate the available "shape sets" and downloading them as needed (with optional caching).
Fascinating question. If you really want to go for plug-ins then OSGi would probably be the way to go, but it's a lot of work to get to know and to use and seems like overkill in this case.
I don't know how your shapes are defined, but they are probably each defined in a separate file-set, providing the shape (maybe a png or jpg?) as well as the audio-file that will be used as a command for this shape. If the folder in which these file-sets are stored is fixed (TapGame/Shape Sets/...) the app could scan the folder each startup and the views could be generated accordingly (in this case, the activity cannot be build entirely in the XML-File, but must be partially done programmatically).
The Plugin-Aps would be rather easy. They are an apk which includes the file sets (jpg and mp3 or whatever). Started once they deposit all these files into the specified folder (they probably check before if these files exist) and then the apk can shut down again and be uninstalled.
on the next startup the Tap Game App would find the new symbols and include them into the game.
This seems rather straight forward to me. Another way would be to actually store the shapes and audio files on the internet and with each start of the App check if the number of shapes and audio-files has changed and create local copies of new ones. This would mean no downloads of apks... probably a more usual approach to the issue.
I am very interested to hear what you make of it, seems like a different approach then the norm, which is always cool to see.

Is it possible to make use of the Android resource resolver on a self-created folder in the file system?

I'd like the ability to "overwrite" the Android resources packaged within my apk by having the app periodically download a zipped file containing overrides that follow the same naming convention as the source does. For example, the zip might consist of the following paths:
res/values/strings.json
res/values-land/strings.json
My code would parse those files and produce a Map> that would map the string resource id to a folder->value pair (or something along these lines). At this point I'm really only concerned with strings and images (maybe arrays), but not layouts, etc.
To the point: Is there any method available, that, given a list of folder names, would tell me which one the Android resolver would choose based on current state? I'm assuming this is difficult because the compiler breaks everything down to ids, but figured it was worth a shot. Any ideas?
Is there any method available, that, given a list of folder names, would tell me which one the Android resolver would choose based on current state?
No. You are welcome to roll this yourself based on Configuration, DeviceMetrics, and kin. You will also need to create your own parsers for your own files, as Android's resource system only works with resources, not arbitrary files retrieved from arbitrary locations.
The expectation in Android is that if you want to update resources, you update the app, probably because there were also code changes as well. Admittedly, this approach has its limitations.

Is there a way to add or change Android apps language after packaging it into an APK?

In the case of a windows application(EXE/DLL), we can change or add language resources within the binary without re-compiling it. Can the same be done in case of an Android application? Is there any editor available to make this happen?
My plan is to develop the application in English and then release it to the sales department, where they will be responsible for the localization of the application without compiling and packaging it into a new APK. I just want to split the development part and localization part of the app.
The correct way to localize is to create a string resource for your base language and then have that localized and reimported into your project for every language that you support.
Much more detail can be found in the Localization documentation.
I don't believe there is a safe/supported way to inject localized strings into your app after it's been built.
No. You can not, because once your apk is signed then modifying it after this (you can always do that as apk is just a zip file) will corrupt the signed binary.
When having multiple languages with your application you have to build them into the application itself. Android uses XML files to store strings used within your application. Android allows you to add language localization files containing local specific strings. You can't do this without recompiling your project so you'll want to do it as a future update or right from the start. But you can't have the marketing department do it, that's just not a good idea.
As others have said, the short answer is no. The long(er) answer is sort of. If you pack all your language resources into remote XML that can be updated from the web, then with a little bit of forethought you can do all sorts of live updates to your app's strings, graphics, etc.
So if you want to use the standard R.string method for everything it will be a little difficult. I think it's possible to do something funky with a dynamic classloader for the assets and static dex classes (basically classes of data with just inline byte arrays that can be decoded after). However that would still require compiling. See Custom Class Loading in Dalvik for more info.
Another approach would be more of a standard Java implementation. Java has a class known as ResourceBundle. You could create a ResourceBundle from a property file (key-value plain text, or even property xml). Then these files could be loaded outside the apk, via a network connection or sdcard or other file type resource and deleted as necessary. You will have to write the loader code for it, but that's going to happen with any solution. This solution will be less performant and outside the standard design methods for android but it will solve the problem being asked to solve. Like you won't be able to use R.string or #string/whatever for any of these resources but I think you may be able to write an adapter to such resources (like your own TextView extension and whatever that would allow all of this). It's a matter mostly of how much work you want to invest in solving this actual problem.
Honestly I would opt for trying to distribute whole apks with only the targeted language if you are trying to save space, but then there is no way to change locale for the app at runtime :(

Configuration file in Android. Does that exist?

I have some configuration I want to save it in my Android application and read it whenever I need , for instance, the server URL that it should try to access like that.
Is there any similar mechanism like web.config in ASP.NET available in Android?
A central configuration file that can be set up manually and then read by the application? Any help would be appreciated!
We use a .properties file in assets folder. It works out very well for us as we support multiple carriers with this, write to it (in case some values, sent from server, need to change. This is done at app start time, thus making our code configurable from server).
You can throw things like that into your strings.xml file. But, since you can't actually modify these values in real-time (since it's a distributed application rather than running on a server), throwing it into a constants class is quite acceptable.
Use Shared Preferences.
Here's a link Shared Preferences
You can use sq lite database files for it. You have a native API to read and write those and on top of that a command line tool.
If you want to create an XML file instead, then it's no different than any other xml file (unless you are thinking about the Shared Preferences, which use an xml format to save the data, but I believe it's not the best API for your application).
I was stumped on this too, but came across Managed Configurations in the Android documentation.
Managed configurations, previously known as application restrictions, allow the enterprise administrator to remotely specify settings for apps. This capability is particularly useful for enterprise-approved apps deployed to a managed profile.
It allows you to set a default value in case you rather not getting into the enterprise admistration business but leaves that option open for the future.
There is a caveat. This only works if your app is registered for EMM. Otherwise you will retrieve an empty map of restrictions.

Categories

Resources