I am attempting to add Firebase Analytics and Crash Reporting to my app. I added the app in the Firebase Console. I made the updates to gradle and added the firebase core and crash reporting libs as dependencies.
My app is broken into multiple subprojects. Each has a slightly different package name:
app/org.mythtv.android.app
tv/org.mythtv.android.tv
presentation/org.mythtv.android.presentation
domain/org.mythtv.android.domain
data/org.mythtv.android.data
app and tv are two high-level subprojects that separate the app from the android tv version, presentation is common components for the 2 previous interface layers, domain encapsulates the interaction with common logic when dealing with data, and data is where the interaction with the backend occurs.
They all share a common package: org.mythtv.android
The application id is org.mythtv.android.
I created an app in the Firebase Console based on org.mythtv.android and added the google-services.json to the root of app and tv. I then wanted to track the crash reports in the other layers as well. Gradle fails to build at this point as it can't find packages org.mythtv.android.presentation and org.mythtv.android.data. These are both Android Library subprojects. data is just a java subproject.
Does the Firebase console need to have a separate app per package and each needs its own separate google-services.json? Doesn't this kind of defeat the purpose?
It sounds like you already got to the root of the problem, which is that you're only supposed to copy the google-service.json apply the google services plugin to application projects, not library projects. The plugin wants to make some changes that are only relevant for apps.
To help others with the same problem, the error message looks like this:
* What went wrong:
Execution failed for task ':mylibrary:processReleaseGoogleServices'.
> No matching client found for package name 'com.google.mylibrary'
Where "mylibrary" is the name of your own library project.
To be honest, I think the plugin should detect if it's being applied to a library project and fail instead with a better message, so I'll see if we can get that remedied.
As an aside, you may want to consider merging your two app projects into a single app project with two different flavors, one for app and the other for tv. They can then share everything by default, but have separate configurations to target different API levels and even have different sets of resources, assets, manifest items, and even independent code, if you're careful. This should simplify the structure of your project. You can read build variants here:
http://tools.android.com/tech-docs/new-build-system/user-guide
Firebase Analytics reports based on the application package name. The package name is not related to the packages you use for your Java classes. The two are independent. The application package name is used by Android to identify your app (for update for example) and can not be changed once you release your app. If you are using gradle you can find it in your app/build.gradle as applicationId value or in your AndroidManifest.xml package attribute.
Related
I am already using an application(has app module) which uses conversations.im as the base. This application has free, paid etc product flavors and debug and release build types. This project already has firebase integration and has 2 applications integrated. I have one google-services.json file in the root directory of the app module.
Now I want to move away from conversations.im(ejabber) and want to implement a separate chat component using cloud firestore. I have created this component as an android library module which I will use in my existing app module.
I want to have separate chat data for this chat library for debug and release types. This will require me to have unique application ids for this library module. But documentation says I cannot have applicationId in a library module.
I am confused where to keep the google-services.json files, in library module or in the app module which will use the chat library module. Looks like can't keep in library because of limitation. And if I keep in app module, library chat module can't work as a separate module in itself.
How should I go about this setup so that I could use different google-services.json files for debug and release types and at the same time make this new module as a library.
Logically speaking, any android project should be able to use the library module and all the chat data should belong to the project and not tied to the chat library. If I go by this approach, google-services.json files should reside within the app module and not library module.
I figured out that we don't have to put the google-services.json file in the library module. We can keep them in the app module which uses the library module.
Now the next question is, is it possible to view data sent from different build variants of the same app under different application views so that we don't accidentally corrupt the test data and production data in firestore?
I have sorted this.
I had to create separate project to keep my firestore chat data for staging and production separate. This is because firebase console does not show the firestore chat data application wise. It shows the chat data project wise. Therefore irrespective of your app's build-variants, data will always flow into one firestore db. And just in case we want to keep our test and production data clean, creating a new firebase project is the only way out.
Thanks everyone for reading the question.
This question already has answers here:
How to make a .jar out from an Android Studio project
(11 answers)
Closed 5 years ago.
I want to create some library that i will use in the future beside my current project.
I can't find a way to create library in android studio.
How to do it on android ?
A library module is useful in the following situations:
When you're building multiple apps that use some of the same components, such as activities, services, or UI layouts.
When you're building an app that exists in multiple APK variations, such as a free and paid version and you need the same core components in both.
In either case, simply move the files you want to reuse into a library module then add the library as a dependency for each app module.
To create a new library module in your project, proceed as follows:
Click File > New > New Module.
In the Create New Module window that appears, click Android Library, then click Next.
There's also an option to create a Java Library, which builds a traditional JAR file.
Give your library a name and select a minimum SDK version for the code in the library, then click Finish.
Once the Gradle project sync completes, the library module appears in the Project panel on the left.
If you don't see the new module folder, make sure it's displaying the Android view.
Visit https://developer.android.com/studio/projects/android-library.html
As introduction I would suggest you to peek into this conceptually simple tutorial. Basically you can start your own library module when you chose your project, without adding any Activity. Then you create your Java Class, usually with a View. When your library is ready, with all its business logic, you can glue everything inserting in the top level build gradle the instruction you are using a library, basically before you remove the following line, that is not needed for a library:
applicationId
(This line in your gradle file is a unique application ID that looks like a Java package name, that identifies your app to the device you are running and in google play)
and then you change this line:
apply plugin: 'com.android.application'
to:
apply plugin: 'com.android.name_library'
When you have a more structured project you can follow the official documentation
As it is well explained the difference between a normal Application and a Library is:
An Android library is structurally the same as an Android app module. It can include everything needed to build an app, including source code, resource files, and an Android manifest. However, instead of compiling into an APK that runs on a device, an Android library compiles into an Android Archive (AAR) file that you can use as a dependency for an Android app module.
I would not encourage you to use solutions like web services that do it on your behalf, namely just copying/pasting your existing code. In fact a library often needs specific architectural choices, so is important to consider and learn different factors, is not just writing some business logic is quite complex to explain, but you can imagine that also the choice of what the user can see and modify can be crucial. Also should be as much as possible bug free, because once it is adopted could cause problems to the users. I remand you to a famous post, superbly written where you can find some solution to this aspect.
you can use https://jitpack.io/ is very easy publish an android library. just upload your code to github/bitbucket and paste the repository link on jitpack website. that's all
I am preparing a white label application (called product later in this post) and I want to set up a very good architecture. This will easily and quickly set up a new client by changing the design, activating features...
I have several servers (dev, pre-prod, prod) so the flavorDimensions server are present in the product and the flavorDimension client is on the client side.
I thought of this solution:
Set up one git per customer and one git for the product.
Clients will have access to the product code by git submodule. This allows me to separate the specific code from my client and the source code of the product.
Git -> Client 1
Submodule -> Product v1
Git -> Client 2
Submodule -> Product v1.2
...
Git -> Product v1.4
But I have a problem how to run it all correctly. The use of flavorDimensions client is hard because I need to make a copy-paste (with gradle) from my submodule to the app module before the build.
The generation of this structure breaks Gradle because its need to be synced every time. (Always Sync Now flag on Android Studio)
So I ask myself, is a good architecture or not ? What do you think ?
Or do you have other ideas and how to implement them?
Thanks for your support.
Hmm interesting take on it.
I have done similar things, but not quite like that. I use flavors for the deltas only. For example, themes, skins, app_icons, and Strings.xml. Maybe a few variations in layout or activities, but do my best to keep it generically served to minimize the maintenance of the code for various customer deployments as each additional flavor slows down the CI process significantly.
However, one key difference in what you are doing is you are not building a platform (aka everyone uses the same code GIT repo and API Server per se, you are building stand alone applications to supply full code and everything else to individual customers.
This sounds like it could be a maintenance nightmare, but if your situation requires that customer's get access to the code base for their product flavor, then I guess it makes sense. Not sure why they would get access to the code though as it is your product you are reskinning for customers right?
At any rate, you aren't asking for me to ask your reasoning haha, you are asking about architectural solutions. So here is my thoughts.
Make a task that copies the respective folders into a new module structure exactly like the modules you have now, but with changes to the package name so that they all slightly differ, then run your GIT push. You can run bash files from Gradle, so you can either write scripts and execute them from relative paths or you can write it directly in your Gradle file itself.
So I would update my Gradle to have separate dependency file like libs.gradle
->Put dependencies in that file like ext.libs {gson:"com.whatever:version"}
->apply from ../libs.gradle
->dependencies { libs.gson, etc..}
So i would assume your build task would do
->Create a new Module from All Source by copying files properly with new names if necessary to rename
->if using maven server, then deploy aar or jar for compiled new module
->Create a new dynamic Gradle file libs.gradle to replace current libs.gradle file that is updated source pointer to deployed artifacts
or created module
->run gradlesync, when complete run assembleRelease, then you can do your git push etc..
All of this can be synchronized and done from terminal and localized into commands. Flavors may not help a ton in this area as they are part of the build process so you kinda need pre build processes which you can create tasks to do pre-build, but the key is the packaging of dependencies and updating your libs.gradle file and making sure that you replace it per flavor. Or if you have fixed flavors you can just make a specific libs.gradle for each flavor and update it based on the compiled dependencies.
I don't know your overall picture, but it is all doable. Hope that helps. Goodluck.
I have an application with three different flavours and two build types. The main module defines some common interfaces and each flavour implements them. The flavours correspond to stores : google, amazon and samsung. The app proposes some in-app purchases, which is specific to each flavour.
I implemented a few debug classes to ease the integration tests of the google the flavour. The debug classes implement the IInAppBillingService and an alternative to the purchase dialog. Now the problem is that some debug classes have dependencies on a flavour. I can't switch to another flavour without having compilation errors.
I would like to keep these test classes, as they are used in integration tests. Also, they should be kept away from the release build type, to avoid any debug/testing code appearing in the released version.
My question is : how to define classes with dependencies on a flavour, but that are not used during the building of the release version ?
As you probably know, you can put code and assets specific to a flavor in its own folder under src. For example you can have folders such as google, amazon, and samsung for each flavor. You can also create debug and release folders for classes and assets specific to each build type. This is useful if you have code only used for development but that should not go into the final release version.
You can take this a step further and create folders for any combination of build type and flavor, for example, googleDebug or amazonRelease.
For automated testing, create a test folder for unit tests which run locally on you development machine or an androidTest folder for instrumented tests run on a device or emulator. These can also be combined with build types and flavors, for example androidTestDebug, androidTestSamsung, or androidTestSamsungDebug.
All classes for testing should go under
Instead of having the classes that handles the billing logic in the flavour folder directly, I used another module specific to a flavour.
In the google billing module, I keep all the classes involved in the in-app purchases. Each module specific to a flavour is imported for the corresponding flavour. This way, I avoid mixing code specific to different flavours.
For example, in the build.gradle file I have :
googleCompile project(path: ':inappbilling_google')
In the inappbilling_google module, I have all the classes involved in in-app purchase through Google in-app billing. There is a debug folder to keep all the classes that should not appear during the release build process.
I was quite happy with this solution, as I keep clearly separate the code of the different flavours and build types... until I discovered that Gradle had some limitations. Indeed, the code present in the debug folder of modules is not included during the compilation. This is a known issue (limitation) of Gradle and the Android Gradle plugin.
However, the Google team and Gradle team have worked on this and have announced a solution to this, with the version 2.5 of the Android Gradle plugin.
In a near future, it will be possible to separate our code using the Android Gradle plugin only. Good news !
I am making an Android app with Wear capabilities.
I want to share some code between the wearable and handheld modules. Specifically, I want to share communication code that uses Google Play Services classes, e.g. com.google.android.gms.common.api.GoogleApiClient.
The obvious way to do this is to have a module (I called it common) and add a dependency to it in both the handheld and the wearable modules.
Since this common module uses Play Services, I need to make it depend on com.google.android.gms:play-services.
I was not sure what to put for the version number - the official documentation here says to use 5.0.77, but that does not work, as the latest SDK does not have this version anywhere, instead it comes with 5.0.89 and 5.2.08.
If I use 5.0.89, the Wearable app does not work, with this error: Google Play services out of date. Requires 5089000 but found 5077534. The version on the watch is older than the one I used to compile.
Instead of depending on com.google.android.gms:play-services the common module could depend on com.google.android.gms:play-services-wearable but then there is a conflict when building because the handheld module depends on com.google.android.gms:play-services, and these two artefacts use the same package name (com.google.android.gms), and so the gradle build fails.
What's the solution?
.
EDIT after discussing a bit and to make my question clearer.
To be able to use communication APIs in my common module I have two choices:
Make common depend on com.google.android.gms:play-services
Make common depend on com.google.android.gms:play-services-wear
⇒ Solution 1 does not work because the version available (5.0.89) for development is more recent than the one on the watch (5.0.77).
⇒ Solution 2 does not work because the handheld module already depends on com.google.android.gms:play-services, which conflicts with com.google.android.gms:play-services-wear.
I bumped into the same problem a few days ago. My shared module depended on com.google.android.gms:play-services as well, so Gradle refused to build and kept nagging at me:
Error: more than one library with package name 'com.google.android.gms
I added this line to my mobile project's gradle file and the error disappeared magically:
compile(project(':sharedModule')) {
transitive = false
}
Take a look here: https://github.com/tajchert/SWear_Weather
I had created common project that is shared between mobile and wear, and contains my constants. Remember to set there dummy manifest file and:
apply plugin: 'com.android.library' in build.gradle file.
I had also encountered problem with play-services version - I had solved it by using
compile 'com.google.android.gms:play-services-wearable:+'
compile 'com.google.android.support:wearable:+'
instead of specifying particular version - to be honest it should be separete question - as it is out of scope of previous (sharing code between projects).
It is possible to need invalidate cache/restart after changing - you can/should remove build paths in your projects to get rid of all other versions.