I have a fully functioning program that worked. However it had two dialogs that I know I'll be reusing every time I write a program, or potentially multiple times per program. They are a EULA and an info page. So I've moved the two activities to their own project, however I don't want to have a standard EULA and info page obviously. So I have the resource on the projects I'm working on. (If using Assets will work better, I could change that.)
For the EULA I have a static function checkEULA to see if it's already been accepted and that works because I pass in an activity and the resource ID.
However for the InfoActivity I am trying to do it as a pure Intent.. I can pass in the id into the bundle, but is there a way to get the activity or resources from the intent with out adding it into the bundle?
Or if not, what is there a best practice, or a smart way to pass a resource into a intent to get it out on the other end?
You can probably do this using the PackageManager class. I believe it will allow you to access the resources from any package on the system.
http://developer.android.com/reference/android/content/pm/PackageManager.html#getResourcesForApplication(java.lang.String)
That being said, I'm curious how you plan to distribute this. Are you going to tell the user to download two different packages from the Android Market?
You might want to consider looking into the library project support that was added in the latest version for the Android SDK tools:
http://developer.android.com/guide/developing/eclipse-adt.html#libraryProject
http://developer.android.com/guide/developing/other-ide.html#libraryProject
Related
My scenario
I have to implement a "modular" android app. There is a core module from which I should be able to invoke other modules. Each module provides a different feature to the user. Imagine I am making a city guide, then one module may contain a map with POIs, another one an event calendar and a third one pre-defined city guides. The modules contain views to be loaded in activities of the core module (like dashboards where each module puts its item/picture). They also contain activities which should be invoked (like when a user taps an item on the dashboard). As far as I know, I will need a database and/or preferences only in the core module. The "plug-in modules" use classes (utilities) of the core module, e.g. when connecting to the backend.
My solution on iOS
For iOS, I achieved this with targets in XCode. I have one project and depending on the customer's needs I compile only the relevant modules. It would be even better if the user can install modules whenever he wants, without the need of reinstalling the "core" application.
My problems on Android
In SO, I already found various solutions like library project, switching from Eclipse to Android Studio + something, using package manager and broadcast receiver... But I still don't understand... How is the modularity of an android application to be achieved?
Here are some concrete problems that I see:
Libraries: My modules all use classes of the core module, so they are not independent. I achieve the modularity by using interfaces/inheritance depending on the flexibility that I need.
Broadcast receiver: This seems to be everything else than recommended. See, for example, here or here.
What I need is, at least, to be able to use the same code for delivering app with features A and B to one customer and with B and C to another one. And, until now, I have no idea how to achieve it.
PS: I don't want to use scripting, I am not familiar with that.
I don't see this "modular" app as anything different from one app, with several packages, each containing discrete functionality, that is adapted to some list of settings or external parameter (either provided by the user or you).
My approach would be to have a "main" package. That package would contain the shared functionality you mention above and serve as the hub for your application. I would then create separate sub-packages for the different "add on" functionality. This allows you to still use the code in your main package with a simple import statement. From your description these additional functions should probably be implemented as a Fragment. A Fragment is almost a stand alone application with the exception that it is "hosted" by an Activity. Depending on how these add on functions are used (I cannot tell if they relate to the UI, just background processing etc) you could easily have 3 of 4 different fragments and choose to load only 1 or 3 or 2 of them at runtime.
To control which parts of the code are used I would just set up a simple switching class (it could even be part of the first activity launched, I cant tell from your description above). Here I would check for some setting indicating which parts of the app will be "active." This could be easily defined using SharedPreferences to store a specific configuration, e.g. use A and B, prior to delivering the final project. You would then just initialize the fragments you need and display them either (1) individually in a Fragment layout element or FrameLayout; (2) collectively in some other view structure like a ViewPager.
I follows your links on the BroadcastReceiver and I am still not sure why they are "everything else than recommended." Used correctly a BroadcastReceiver is very useful. I tend to use a LocalBroadcastManager along with a BroadcastReceiver to notify other sections of the app when some AsyncTask, e.g. downloading a lot of data, is complete. These parts of the app can then access a local database or process the information downloaded on their own time. I wouldn't use a BroadcastReceiver to modulate parts of the app if that is what you're looking for. I would instead just use a SharedPreference file to set the configuration at runtime.
If you need modules like facebook sdk or something like that better use library project. If you use Idea or Android Studio there is such thing like Module. If I need some modeles in one app I prefer just put in different packages like com.appname.model, com.appname.ui and so on. Broadcast Receiver isn't about modules. As I know there isn't analog of ios target.
The project I'm working on requires that N stand-alone applications can be built but also an extra big application with a selection menu that will execute one of those.
The difference between these applications is mainly resources and XML, so they all use a common library which reacts to assets and the information provided in the XML.
The problem is regarding the "mother" application. It has to be able to use the common library using one of the stand-alone resources set. I realized I can access another application resources using:
Resources R2 = getPackageManager().getResourcesForApplication("com.example.appa");
int id = R2.getIdentifier("image", "drawable", "com.example.appa");
Drawable myDrawable = R2.getDrawable(id);
And this actually solves the issue, I can supply a package string to the library so it will know where to look for the resources.
Problem is, in order for this to work, I need to have those stand-alone applications installed on the device, and that's something I cannot do (think of it as a quiz application, the stand-alone apps are only one topic while the "mother" app allows access to all different topics and, as far as I'm aware, Android Market won't allow downloading all apps and installing them just so I can access their resources).
Conceptually speaking, this issue would be solved if I could make those stand-alone applications as libraries and adding them to the mother app. The mother app would then use a package string depending on user choice and then use the library. So far I haven't been able to work this out and I can't find information about this so I'm afraid this can't be done.
Each topic application has, for example, an intro.png with an image regarding the topic of the app (for example a roman or a greek image) and the idea is to access package_string.intro.png so it will automatically access the right one depending on user choice.
After struggling to do this I finally found out resources are indexed which means only one "intro.png" exists in one application, no matter how many libraries you try to link, you can't create a reference to lib1.intro.png or lib2.intro.png. I finally built a resource manager system which works with "lib1_intro" or "lib2_intro" on demand. Not the cleanest of solutions but, meh, it works I guess...
Moving my edit to an answer as I read about accepting answers and this is how it should have been done instead of just editing my first post
I have a single android app with a custom logo, some custom json service endpoints, occasional custom text, and possibly a custom color scheme.
For my client this particular app will need to be rebranded and distributed as an entirely different app about 5-10 times over. So I'm looking for way to reuse the most amount of code - the activities and services will be identical except for the custom things I mentioned.
First off, how can I share projects in the sense that one project will hold all code (including activities), and the others just modify a few values. I can't think of a smart way to share both service code and activity code with the occasional value thrown in via properties.
Do android layout/string resource files have the ability to pull from properties? Can activities be bundled inside a jar and shared with other projects?
You can use Android library project to share the common code. Start by reading this article
You do not have to have different java namespaces, they can be common for all projects. All you need is to replace resources and modify manifest to contain different namespace for each application. There is no problem with several applications having the same name of classes inside. Unless you want to rebrand it all the way user could not find it is actually the same code, of course.
I am very new to eclipse and android developing in general and need help with the following. I have built two android projects in Eclipse with the android SDK:
"ORF401 Project" - targets Android 2.2 platform
"Map Project" - targets Google APIs 2.2 platform
I have followed the steps as specified by the standard Hello World Google Maps for android tutorial and have gotten the Google map to display on the emulator when I run the second project.
I have a menu set up in the 1st project for which one of the options is to load the map. However, I'm not sure how to load the map within this project since only one build target can be specified for each project, and so I cannot specify the Google Maps API as a (additional) build target. Is there a way to call the main .java class from the second project within the first project? I see where a reference can be made to the 2nd project under the project properties, but I'm not sure how to make use of this. One possible solution I found on the web was to add the following code under the switch case in the first project:
Intent intent = new Intent(this, {googleMap}.class);
startActivity(intent);
I presume this would require an additional googleMap.java class in the first project and also another activity, but I can't get it to work. Can anyone make a suggestion as to how I can accomplish this?
If the code for either or both projects would help, I'll be happy to post it. Thanks
The main idea with projects is to have one project per application that does some thing.
I assume your application needs to do something with maps, as well as something else. There is no need to split those ideas. Keep them in one project, because they make up one single application that you develop.
First thing I would suggest - read carefully about activities and intents. Head to http://developer.android.com - everything's clearly explained.
With that all cleared up you will see the point in making some button, which, being tapped, opens a new screen with the map feature that you've developed. And then let's you go back or do something else, like open a new screen, a browser, etc.
And give up trying to call the other project from a different one :) It's not the way I think you want to do stuff.
Just to make sure I'm not misunderstood - of course you might want to have two projects. But those will most probably result in two separate applications. Luckily, applications may also interact by intents, or content providers, or a couple more. Just see how Contacts app takes you to GMail app if you want to send a mail. If that's what you want to achieve - still need to read about intents.
edit:
Here's the link I mentioned about in the comments:
http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html
It explains how to achieve the 'additional target' that you would like to have.
There are ways to call a class from one project in another project, but there are bigger problems here. The first project can run on any Android device. The second, however, requires Google Maps APIs. You won't be able to invoke it anyway, because it can't be installed unless you're in an environment that supports Google APIs. There really is no benefit to doing this, unless you have additional functionality in project 1 such that it can exist without project 2.
I would suggest using the Intent method rather than trying to hack something together that allows you to access another class. Regardless, though coupling these two together like this seems overly complicated and error prone. I would suggest simply embedding the mapping functionality in project 1 and requiring Google APIs. Most mainstream device support them anyway.
If you're married to the idea of having two separate projects with different build targets, I would suggest looking into using BroadcastReceivers with a custom intent that you broadcast from application 1. I don't believe startActivity will work across application boundaries because of class loader issues, but I could be wrong about that.
If I needed to build an android SDK that other developers can integrate into their android apps, is jarring my SDK the only way to go about it? As far as I have learnt, jarring has the following considerations:
If your app uses a layout, then you have to create it programmatically. Since jar files cant carry any resources.
The jar will needs to be placed in the lib/assets folder and added to the build path (in Eclipse) -- Learnt here: Android - Invoke activity from within jar
The main app will have to create an Intent object and specify the package and class name in the jar to start the activity.
Any one have other ideas of going about any of the above steps?
Thanks
George
Creating a JAR is, in my opinion, a very bad decision. Android has specific features just for the kind of thing you're looking for. If your JAR:
provides some sort of (structured) data to be used in other applications, use a ContentProvider;
does some backround processing and makes that processing's results available to other applications, use a Service;
provides an Activity that gets some input from the user (or shows some information about something), eventually processes it and returns it to the calling Activity, just create that Activity and any application will be able to start your Activity as long as it's installed on the phone.
If you use one of the three solutions above, third party apps will be able to probe for whether your application is installed and, if not, prompt the user to install it. Only if your application does not fall into one of the three bullet points mentioned above should you use a JAR. Otherwise, using a ContentProvider, Service or Activity provides:
More standardized interaction between components
Better maintainability -- if you update your SDK you won't have to call everyone who uses it and tell them to upgrade.
No duplication -- if you were to provide a JAR and multiple applications that use it would be installed on a device, multiple copies of the JAR would be present on that device, thus using more memory than it has to. If you provide one of the three components mentioned above, one copy will satisfy all applications that need to use it.
Again, these components are specifically designed and provided by the Android OS for creating such SDKs. Please, only use a JAR if you really, really have to. Otherwise, provide a standardized ContentProvider, Service or Activity and document the way it's supposed to be used (i.e. how to use/query/integrate it).