Using Realm in a Cordova plugin for Android - android

I am experimenting with using Realm in place of SQLite in my hybrid Android/Cordova app which uses one custom - i.e. written by me - plugin. From the Realm documentation I have figured out that this has to be a two step process
Instructing Gradle to use the Realm plugin which I am doing via my plugin.xml file as io.realm:realm-gradle-plugin:6.0.2
"Applying the plugin" which according to the documentation involves issuing a apply plugin: 'realm-android' from the application levelbuild.gradle`file.
It is not clear to me how I do the latter. I tried putting the "apply plugin" statement in a build-extras.gradle file only to have Gradle complain
plugin with id 'realm-android' not found. Clearly, I am doing something wrong here. I'd be grateful to anyone who might be able to put me on the right path.

Sorry to destroy your delusions, but this assumption is just wrong:
Instructing Gradle to use the Realm plugin which I am doing via my plugin.xml file as io.realm:realm-gradle-plugin:6.0.2
I'd expect that to be required for the root project's build.gradle:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:6.0.2"
}
}
allprojects {
repositories {
jcenter()
}
}
As well as the module level build.gradle:
apply plugin: "realm-android"
...
dependencies {
// only this one line can be added through plugin.xml
implementation "io.realm:realm-android-library:6.0.2"
}
However, I think that Cordova by default only supports adding Java dependencies through plugin.xml, but no Gradle plugins - therefore you'd likely need to patch both build.gradle on demand, with a script similar to patchAndroidGradle.js, hooked into before_plugin_install. This obviously would then also need to be un-patched again, upon before_plugin_uninstall.

#MartinZeitler's answer is what put me on the right track here. For a Cordova project here is what you need to do:
Step 1
Open the platoforms/android/app/build.gradle file and in the dependencies{..} section add classpath "io.realm:realm-gradle-plugin:6.0.2".
Step 2
Now open the platforms\android\build-extras.gradle file - this is not created by default in Cordova so you might have to create a new one - and enter the following text
ext.postBuildExtras = {apply plugin: 'realm-android'}
Save the two files and perform a full rebuild of your project.
A few words of explanation are in order here. The mistake I had made was thinking that what was being supplied by Realm was a Java library. Not true. What you do in Realm is to model your data in the form of subclassed RealmObjects. Typically you will have multiple sub-classes of this type to fully define your data model. These sub-classes with their annotations are in effect instructions to Realm where you tell it how you are going to manage your data. As noted in the Realm docs
An annotation processor will create a proxy class for your RealmObject subclass.
The plugin you are incorporating into your project here is a Gradle plugin which extends the capabilities of Gradle. In this instance it is allowing the Realm annotation processor to examine your data model classes and create its own proxy classes. You can read up on how Gradle uses plugins here.

Add at the bottom :
apply plugin: 'realm-android' in the file build.gradle which is under the app folder of your project

Related

How to add a class / an enum to settings gradle script on gradle 6.0+?

I want to add an enum called modules with the path of the sub module and some compilation types.
I used to have this in the buildSrc before gradle 6 and it was accessible in the settings.gradle
But from gradle 6.0, settings.gradle is compiled before buildSrc project. I have moved my enum to the settings.gradle, now it is not accessible to other project level gradle scripts.
The behaviour change is outlined in the below release notes.
https://docs.gradle.org/current/userguide/upgrading_version_5.html#changes_to_plugins_and_build_scripts
They suggest to add the enums / classes used in the settings.gradle to the build script closure, but I am not really sure how to do that.
https://docs.gradle.org/current/userguide/upgrading_version_5.html#plugins_and_classes_loaded_in_settings_scripts_are_visible_to_project_scripts_and_buildsrc
I've recently hit a similar issue, my company have custom code for authenticating with our Nexus which we were keeping in buildSrc. I can't turn this into a plugin since I'd need to store that in our Nexus and then would be in a catch-22 situation as I'd need to authenticate to get the authentication plugin!
I can see 2 potential workarounds for this:
Publicly published jar.
Build your custom classes as a separate jar, or a Gradle plugin if this fits the use case. Publish the jar to a maven repository that you can access from settings.gradle buildscript (for me this is difficult as it's sensitive company specific code).
This might look something like the following in your settings.gradle:
include "project-name"
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.companyname:gradle-utils:0.0.1'
}
}
Commit the binary
This isn't a desirable option but you can manage the source code for your custom buildSrc classes in another repository, then every time you make a change to them (hopefully infrequently) - you can build the new version and commit the built jar into the repositories that need to use it (perhaps under buildSrc). If your custom code has dependencies that aren't naturally on the classpath when gradle runs, you'd need to package these into the jar that you commit as well.
Your settings.gradle might then look like:
include "project-name"
buildscript {
dependencies {
classpath files("buildSrc/gradle-utils.jar")
}
}

Reusing the same code across multiple Android Studio projects

I have some code I'd like to use across multiple different projects. Let's say it's some e-commerce code that handles things like payments and shopping carts.
It seems inefficient and dangerous to copy-paste everything across different projects. And if I add one feature or fix one bug in the core e-commerce module, I'd like that change to be reflected in other projects using it too.
I would also like to re-use some of the Activities, Fragments, Adapters too.
What is a good approach to this?
When we have a library project that needs to be shared to every project on a local computer, we can make use of Maven.
A. Here the step in your library that we will you for the project:
Make a library project from Android Studio.
Add Gradle Android Maven plugin to root build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
}
}
Add apply plugin for step 1 in your library build.gradle. (NOT root build.gradle):
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
Add the following after the apply plugin, this line to determine your library when adding to project:
group = 'com.yourpackage.yourlibrary'
version = '1.0'
Add the following code in your settings.gradle:
rootProject.name = 'yourlibrary'
Then publish it to your local maven with:
./gradlew install
Or you can use gradle option in Android Studio.
Your library will be installed in $HOME/.m2/repository. Remember that to use the library you need to add like this:
Groupid:artifactid:versionid
Artifactid will be package name of your library.
B. Here the step in your Project which using the library:
Add the following code in your root build.gradle:
mavenLocal() // for local maven.
This for getting the local library maven that we have installed in step A
Then in your app project.gradle, add compile for the library:
compile 'com.yourpackage.yourlibrary:yourlibrary:1.0'
Read more:
Gradle: How to publish a Android library to local repository
https://github.com/dcendents/android-maven-gradle-plugin
https://inthecheesefactory.com/blog/how-to-upload-library-to-jcenter-maven-central-as-dependency/en
From my Knowledge 1. As others said try creating your own Module or Library and use it where ever you need 2.Use Version Control Tools Like Git(If your code changes it will be refleted in your git account)

How to obtain firebase libraries, e.g. firebase-messaging-9.4.0.jar

I am trying to do an automated android build in a local network segment (ie. without access to public jcenter or maven repositories). In order to do that I need to provide all dependencies in a local maven repository which is referenced from the root build.gradle. (NB: if I use the android-maven-plugin instead of gradle the situation is the same).
This works fine, only I have difficulties locating the firebase libraries like firebase-core-9.4.0.jar or firebase-messaging-9.4.0.jar. According to the gradle console output they are searched in a location
<server>/com/google/firebase/firebase-messaging/9.4.0/firebase-messaging-9.4.0.jar
This location does not exist in the public jcenter or maven repositories.
Does anyone know where to find them?
edit: I have observed Android Studio on empty caches using Wireshark (using http for the jcenter repository). The results are rather mysterious. It issues a GET request for
http://jcenter.bintray.com/com/google/firebase/firebase-messaging/9.4.0/firebase-messaging-9.4.0.jar
This request is redirected to
http://repo.jfrog.org/artifactory/libs-release-bintray/com/google/firebase/firebase-messaging/9.4.0/firebase-messaging-9.4.0.jar?referrer
The latter GET request results in HTTP 404 as the repo.jfrog.org repository has no content in the firebase-messaging/ directory. However, Android Studio extracts the jar files in the build directory and continues to build the project.It is unclear, where the jar files come from.
You can show all librarys in the oficial support.
https://firebase.google.com/docs/android/setup
Found this link, hope this help
https://github.com/unity-plugins/Google-Firebase-SDK
According to this, you should add to you build.gradle:
buildscript {
// ...
dependencies {
// ...
classpath 'com.google.gms:google-services:3.1.1'
and that to your app/build.gradle:
apply plugin: 'com.android.application'
android {
// ...
}
dependencies {
// ...
compile 'com.google.firebase:firebase-core:11.8.0'
// Getting a "Could not find" error? Make sure you have
// the latest Google Repository in the Android SDK manager
}
// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'
Update 2020
Firebase aar are now available on maven repository at https://mvnrepository.com/artifact/com.google.firebase
For example, firebase-core aar is at https://maven.google.com/com/google/firebase/firebase-core/17.4.4/firebase-core-17.4.4.aar

Gradle: "apply plugin" at the top or at the bottom

Has the same effect add the "apply plugin" at the beginning or end of the file build.gradle in Android Studio projects?
For example to add the 'com.google.gms.google-services' plugin, Firebase official documentation recommends adding at the end, but I've seen other codes add it at the beginning.
I know the question seems irrelevant, but I'm developing a plugin for Android Studio to manage dependencies and have this doubt.
Thanks in advance
Gradle scripts are interpreted top to bottom so order can be important. Keep in mind that gradle has a configuration phase and an execution phase so sometimes order isn't important. It's common to apply your plugins at the top of the script since plugins often add extension objects and tasks to the gradle model which can then be configured lower down in the build script.
For example, you can't do the following because the test task is added by the java plugin:
test {
include 'org/foo/**'
}
apply plugin: 'java'

Best practice for buildscript tag in build.gradle of library projects

I'm wondering what is the best / intended way of defining build script repositories and dependencies for Android library projects.
Out in the wild (like Github) most of the repos define the following in there build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
} }
But if I create a library project in Android Studio this buildscript block does not get created, as it is already in the root build.gradle file, and therefore not necessary (I assume).
So what is the proper way, only defining it once in the root build.gradle or for each library project (which also means updating the version number for each library in case of new plugin versions). Or does it depend whether I want to release the library independently from my main application?
If you're developing a library, there isn't really a top-level build.gradle: that top level applies to all modules in a multimodule project, but a library is best implemented as a standalone single module.
Probably the best practice would be to have a single build.gradle file for your library module, and include a buildscript block in it with the repository and Android plugin Gradle version. That way it stands alone better, and it's not implicitly dependent on being in a project that has a top-level build.gradle file.
There's a huge caveat which kind of renders a lot of this moot, however -- if you include this module, with its own buildscript block, in a project that has a top-level build.gradle with a competing buildscript block, the top-level build file will win and it will ignore the block in your module.
This probably isn't much of a problem, but if your module relied on a specific version of the Android Gradle plugin, for example, and it was in a project that used a different version of the plugin, then your module would lose and it could run into problems. Another way of saying it is that it can only use one version of a plugin for all of the modules in a single build, and I believe the first one to specify it sets it for everyone.
In practice, this is only likely to be an issue if you rely on some feature specific to a later-than-1.0 version of the Android Gradle plugin, and it's included in a project that uses 1.0.
There are some subtleties here that I'll mention but won't answer (and I apologize for answering your question with more questions) -- if anyone else knows for sure, please answer yourself, or edit my answer, or mention it in the comments:
What if your buildscript block adds new plugins to the classpath? Do they get added or are they ignored?
What if your buildscript block adds new repositories to the search path? Will they get picked up?

Categories

Resources