Android - How should you manage multiple modules? Manifests, grades, etc. - android

I understand this question is vague, but can someone outline the rules and/or how we should be dealing with multiple modules?
I've been trying to separate my app out into a base feature module, application module and instant app module.
However I've been having a nightmare building it.
I've tried searching online but there isn't really much documentation in it?
Ive got two activities in my base module manifest, as I want these in both my installed and instant app. Do I then need to copy these activity manifest entries into my other manifests? I tried running my installed apk without adding in these activities (I thought it might pull it from the base module) but then android studio says can't find default activity to launch the application with. So I need to copy the activity entries into all manifests?
I've also got manifest entry conflicts from all the libraries I'm using. FacebookInitProvider , FacebookInitProvider, CrashlyticsInitProvider etc. I don't have these entries in any manifest, they are adding themselves in to every manifest causing merge conflicts when building.
With the build grades, I've put in the base just the libraries necessary to run the base / instant app (to keep it as small as possible). The installed gradle then has all the extra libraries for the full sized application. If I use
implementation project(":base")
Will it automatically pull in all the dependencies that base uses? Or do I need to redeclare these?
I ask because after getting the app to build, firebase and firestore was causing an exception on getting the instance with the message "Firestore module not found" which makes it look like it hasn't pulled in the dependencies properly?
I apologise for the lengthy post, but I'm honestly at the end of my tether here. Truly stuck!

Im not sure I understand all your project structure correctly so I will give you general information on an app with modules:
Lets say you have the application called "appone" and have a module called "moduleone"
In the module gradle file you declare the minimum you need for the module to work properly by itself and in the manifest just configuration specific for the module that will not be required to be defined in the appone manifest.
Now in the appone manifest, this is the main file, you will have to set here the activity declarations and app permissions (not in moduleone), android studio merges the two files automatically so when you compile it will make one manifest file with both manifests contents so this is what can make conflicts if you declare the same or conflicting data on both files.
In the appone build.gradle file this is where you declare the implementation project(':moduleone'), and the implementation of libraries required by appone.
If for example moduleone uses firebase library and in appone you also directly require access to the firebase library you could declare it in both build.gradle files, you just need to make sure both use the same version.
Also you will need to declare moduleone on the settings.gradle file using: include ':moduleone'
appone is declared as an com.android.application and moduleone is declared as com.android.library.
Also appone has in its manifest an activity declared with the LAUNCHER category.

Related

Dependency missing but exists in APK, how?

I have a MyLocationService library, which has dependency from huawei_location_service.Inside I have HMSLocationService class which is the only one using huawei_location_service classes and I use relfection to access that class. Meaning is, if we run app on Huawei and if there is dependency from huawei_location_service, I will get location, otherwise will not. And application should run perfectly on non-hauwei devices without dependency from huawei_location_service.
So when I build MyLocationService.aar I removed huawei_location_service dependency from it's pom file. After that I created a new application and added dependency from MyLocationService.aar. When I check dependencies with command gradlew app:dependencies I don't see any dependency from huawei, but when I create an apk and analyze it, in classes.dex there are classes from huawei_location_service.
Question: How it is possible? And is there any other way to achieve what I want?
P.S. I analyzed also MyLocationService.aar, didn't find any huawei dependency. Is there another way to check dependencies of *.aar files instead of pom or analyzing tool of android studio?
So if someone will be mistaken as me, this answer will help.
The repositories and classes I saw in classes.dex were not coming from hms libraries. As I have imports in my custom classes, that imports' texts were the reason I was seeing huawei folder in classes.dex. Also take attention on the size, and you can see that they are kind of 20 bytes.
So I removed the imports, generate my library again, created apk and analyzed it and woala, no huawei folder is visible.
P.S. *.aars doesn't contain any library if you not put transitive=true. And you need to add dependencies required by your lib in your own applicaiton.
P.S.S. If you have locally or globally publishing your library, maven(Gradle uses maven) creates metadata, so called POM file, as a helper to identify all dependencies that the library needs.

Default Activity Not Found in Instant App while having 'arch.lifecycle:extension' as dependency

As the title states, I'm having quite of a frustrating time trying to solve this. It seems like it could be a silly mistake that I have overlooked. The issue here is that I want to include the new Android Architecture Component ViewModel into my project structured as an Instant App. I have followed this guideline to add it as a dependency in build.gradle.
As the documentation states,
For LiveData, and ViewModel, add:
implementation "android.arch.lifecycle:extensions:1.0.0"
Now in my AndroidStudio-generated Instant App project structure, I want to make this dependency available to all feature modules. So, I add the above line to my base module, but use the api keyword instead, in order for feature modules to be able to reference it like below
In base module's build.gradle:
api 'android.arch.lifecycle:extensions:1.0.0'
When I now go and add applicationIdSuffix ".dev" to my buildType in build.gradle in the base module, or even change the default applicationId, Android Studio suddenly does not recognize my Default Activity when attempting to run. I have double checked the default activity declaration in my AndroidManifest.xml multiple times, so it is definitely not that issue.
If I remove that dependency from build.gradle, the issue disappears completely and the Default Activity is recognized. This is really weird and would like to know if anyone experiences any issues similar to this.
Note: The Default Activity is declared in a feature module's AndroidManifest.xml

How to access layouts of a sub-module from another sub-module?

I have two modules in my android project. And I want both of these modules to access the layout files of other module and perform operations like Intent().
But, Using compile project (':x ') is not working for this.
Edit:
Both the modules are successfully added into the project and gradle was synced properly and manifests are merged. I want to how to access res/layout files of one module from another module's java file.For context, I have activityA.xml in module 1 which I need in module two so that when a button is clicked in module 2, it transits to ActivityA.xml with intent.
ok so to use resources from another module you must do a few things.
Determine how you will package and use your module. Is the module "just" for this app or is it used in others.
If it is used by more than one project then I recommend packaging it as an AAR and hosting in a Maven Repo of your own and pulling via Gradle to avoid project dependencies on the code base itself.
If it is only used by this project then you must do a couple things as well.
1) Ensure that the settings.gradle has the module included. You can do this with simple :moduleName if it is local to the project directory. Otherwise you can do it with
include 'myLib'
project(':myLib').projectDir = new File('../../../workspace/libs/myLib')
Once you have done this confirm Gradle Sync pulls the module into the project. And not just an empty folder with an IML. If it is an empty folder confirm your path and try again.
Step 2) So you successfully imported your module and you can see it in your directory. However, you can't have a module depend on the app and the app depend on the module. It is called circular dependency, so you must only have the app depend on the module. Go to your app's module the one where it has
apply plugin: 'com.android.application'
and go to the dependency section and include
compile ':myLib'
Now you need to confirm your compile myLib is working (myLib is the name of your lib). To confirm you can do an assembleRelease from the terminal and see if it has any issue or you can do a Gradlesync as well.
If it worked you can now import resources or files into any Activity of the parent app module by simply including the import statement at the top.
Now you can do things like HelperClass.doSomething (where helperClass lives in myLibs).
So let's take it one step further. Maybe you need HelperClass to be able to respond to the app module. Then you must supply an interface inside the myLib of IMyCallBack with whatever methods you would call out to and have the parent module calling activity implement the interface for calling back.
Does this answer your question or are you having another issue. A there should be no issue accessing the content of your child module if your dependency is setup correctly.

What is the right way to insert an activity in another project?

I have an Android Studio project
which consists of a login activity with relative style, manifest, IntentService and other stuff.
I want to insert this little project in many other apps, what is the best way to proceed ?
Is Module the right way ?
The ultimate goal is still to easy maintenance, such as if one day the server should change URL, I would not have to make changes in any application that uses this login activity :-)
You need to extract these components in a separate module:
A module is a discrete unit of functionality which you can compile,
run, test and debug independently.
Modules contain everything that is required for their specific tasks:
source code, build scripts, unit tests, deployment descriptors, and
documentation. However, modules exist and are functional only in the
context of a project.
Then, include that module in all projects using it.
In fact, you can create the module in an independent "library" project of its own. And add it as a dependency for all projects using it.
Going a step further, you can publish the output of an open source library project as .aar or .jar on maven central, jcenter and other public repositories. Then other people will also be able to use your module.
Some important points to remember when creating android library projects:
The resources (strings, layouts, xmls, images) of a library will be merged with those of final project on build. Still your module's R class will stay under your module's package name.
Some attributes from manifest file of library might be merged to that of final project (like that of <application> ). So, a library module should have a minimal manifest file, with at most, the package name.
You may include an example application project inside a library module, but do not redestribute the example app project with library. It will cause trouble for someone building an application using your library.
I think that what you need to do is to export your original project first:
File>>Export
Then go to your new project and import the original one.
Dont forget to amend the setContentView() method to point to your original activity(the one you imported)
and finally dont forget your intent method!
if you have any issues let me know and i will create a detailed answer for you but i think that you will be ok!

Android Library Manifest vs. App Manifest

I've read similar questions here, but am still not clear on a couple of things. Using a Library Project means that my overall project will have two manifests -- one for the library and the other for the "main" app project -- and I'm not clear what goes in which or if there is some redundancy.
I'm developing an app widget with "lite" and "paid" versions, so will have almost all code in a library project. Being a widget, the library will have at least a receiver, a service, a configuration activity, plus a couple of other activities. So where should the full declarations of these components -- including intents, filters, etc. -- be declared? Do they go in the manifest for the library, or in the manifest for the application package itself, referencing the classes in the library (e.g. android:name="com.foo.mylibrary.MyService")?
Some examples I've looked at seem to declare them in both manifests, but I suspect that putting these in one or the other is a no-op.
Using a Library Project means that my overall project will have two manifests -- one for the library and the other for the "main" app project -- and I'm not clear what goes in which or if there is some redundancy.
The library project manifest is not presently used.
Gradle for Android, and therefore Android Studio, support library projects and AARs publishing a manifest. This can include things like activity declarations, required permissions or features, or minimum supported Android SDK levels.
The rules for how library manifests are merged with the app's own manifest -- particularly when you take build types and product flavors into account -- is a bit complex.
So where should the full declarations of these components -- including intents, filters, etc. -- be declared?
In the host project.
The library could publish those components, and the Android Studio host project can then remove them if needed.
Do they go in the manifest for the library, or in the manifest for the application package itself, referencing the classes in the library (e.g. android:name="com.foo.mylibrary.MyService")?
The latter.
In either (with Gradle for Android and Android Studio). In theory, it is easier for the library to publish the components, so the app author does not have to. Personally, I am not a huge fan of this, as too many developers will wind up shipping unnecessary manifest entries.
As of ADT r20 Preview 3 it is now possible to merge manifests. So common configuration can now be put into the library manifest. See https://stackoverflow.com/a/10400355/262789 for more information.
Version 13 of Intellij IDEA is necessary for manifest merging support (manifestmerger.enabled=true). Also the Grade based build system appears to be necessary for Android Studio support.
Any referenced android elements like activities, receivers, services, etc. MUST go into your Application manifest or they won't be recognized by the OS. As you guessed, the Library manifest file is pretty much an empty implementation
UPDATE
As CommonsWare points out above, the Android build tools will now attempt to merge the various manifests on your behalf. Leaving up the original answer for posterity

Categories

Resources