Commit 083db4b2 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

Some cleaning

parent fd714b39
# Introduction
Until today, integrating liblinphone sdk into a third party application required compiling a sdk from the sources or importing sdk binary files from: http://www.linphone.org/technical-corner/liblinphone/downloads
In order to ease integration of this sdk, we adapted a Gitlab repository as a Maven one.
Maven is a standardized tool to manage and build Java-based projects, which core unit of work is Project Object Model.
With Gradle and this Maven repository, we now offer the ability to either host or import remotely liblinphone sdk, as any future library.
Starting with linphone-android release 4.1 the SDK part of the application is generated as an AAR.
If there is no locally built AAR, Android Studio will download one from this repository.
# Branches and version number
# How to produce and host Liblinphone SDK on our Maven repository
AAR are generated by linphone-sdk repository and version name will be the result of the git describe command in this repository.
Then the AAR will be uploaded here, in the same branch as the linphone-sdk was, except for releases.
To host Liblinphone SDK and allow future remote import, follow theses steps:
# Using this maven repository
## Get Linphone-Android and deploy locally Liblinphone SDK
git clone git@gitlab.linphone.org:BC/public/linphone-android.git
cd linphone-android
git checkout -b master origin/master
git submodule sync && git submodule update ~-~-init ~-~-recursive
./prepare.py -c && ./prepare.py && make
## Binary and Maven files production
Inside your app/build.gradle, add the following:
```
repositories {
maven {
// Switch to release for releases !
url "https://gitlab.linphone.org/BC/public/maven_repository/raw/master"
}
}
```
This part requires a private SSH key used to write right to the repository, it must be asked to Simon Morlat, Jehan Monnier, Sylvain Berfini or Erwan Croze.
Then it must be placed into liblinphone-sdk folder.
Then in your dependencies list, add linphone-android-sdk:
```
implementation "org.linphone:linphone-sdk-android:<version_number>"
```
### Settings
You can use `+` to get the latest snapshot version or hardcode a version number you specifically want.
Set the liblinphone-sdk/build.gradle and gradle.properties files as in the maven_repository Git project.
# How are the AAR created and uploaded
liblinphone-sdk/build.gradle:
Here's the gradle tasks used to upload the AAR:
```
def gitVersion = new ByteArrayOutputStream()
def gitBranch = new ByteArrayOutputStream()
allprojects {
repositories {
...
maven { url "https://raw.github.com/synergian/wagon-git/releases"}
}
task getGitVersion {
exec {
commandLine 'git', 'describe', '--always'
standardOutput = gitVersion
}
configurations {
...
deployerJars
exec {
commandLine 'git', 'name-rev', '--name-only', 'HEAD'
standardOutput = gitBranch
}
apply plugin: 'maven'
...
dependencies {
...
deployerJars "ar.com.synergian:wagon-git:0.2.5"
}
///////////// Task /////////////
uploadArchives {
repositories {
mavenDeployer {
configuration = configurations.deployerJars
repository(url: 'git:master://git@gitlab.linphone.org:BC/public/maven_repository.git'){
authentication(privateKey: privateKey)
}
pom.project {
groupId 'org.linphone'
artifactId 'liblinphone-sdk'
version project.hasProperty("debug") ? "4.0.1-DEBUG": "4.0.1"
}
}
doLast {
def branchSplit = gitBranch.toString().trim().split('/')
def splitLen = branchSplit.length
if (splitLen == 4) {
gitBranch = branchSplit[2] + '/' + branchSplit[3]
println("Local repository seems to be in detached head state, using last 2 segments of Git branch: " + gitBranch.toString().trim())
} else {
println("Git branch: " + gitBranch.toString().trim())
}
}
gradle.properties:
privateKey=./maven_rsa
### Options explanation
-configuration: uses settings and deployment forms from wagon-git project, which allows gradle to push right to maven_repository.
-repository: the link to our maven_repository. In case of future modification, keep the 'git:master:~/~/' part, it is needed for wagon-git to handle sending.
-authentification: uses a private key corresponding to the deploy key assigned to this project , defined in gradle.properties.
-pom.project: theses options will define the way we call the dependency in the last part, as following:
'groupId:artifactId:version'
For other libraries or versions, just edit artifactId or version.
Keep the -DEBUG part in the code. Maven favors convention over configuration.
### Production
Check if linphone-android builds on the right device.
Then, in a terminal located at linphone-android's root, type:
gradle clean assemble uploadArchives
or
gradle clean assembleDebug uploadArchives
Warning: If a not working version is produced, before building it again, clear the whole gradle cache ($HOME/.gradle/caches/), or gradle will produce the same.
# How to use hosted Liblinphone SDK as a remote dependency
In another linphone-android project, in which you can delete liblinphone-sdk folder, edit linphone-android build.gradle like the one located in maven_repository root:
## Set our Maven repository source
allprojects {
repositories {
maven{
url "https://gitlab.linphone.org/BC/public/maven_repository/raw/master"
}
uploadArchives {
repositories {
mavenDeployer {
configuration = configurations.deployerJars
repository(url: 'git:' + gitBranch.toString().trim() + '://git@gitlab.linphone.org:BC/public/maven_repository.git')
pom.project {
groupId 'org.linphone'
artifactId 'linphone-sdk-android'
version gitVersion.toString().trim()
}
}
}
}
```
Be sure to keep the raw/master part in future modification, as it defines the true path to files, not the one to navigate in web browser.
## Change our local project dependency to remote dependency
dependencies {
// implementation project(':liblinphone-sdk')
releaseImplementation 'org.linphone:liblinphone-sdk:4.0.1'
debugImplementation 'org.linphone:liblinphone-sdk:4.0.1-DEBUG'
}
Comment release or debug line if no remote library is available for it.
Use the settings provided in the creation part so gradle can find the right dependency:
'groupId:artifactId:version'
In case of another library need or newer version, provided it is hosted, just change artifactId and version in accordance to its declaration in the creation part.
# Sources
All of these links contributed to teach me the way to produce this repository:
https://docs.gradle.org/current/userguide/maven_plugin.html
https://github.com/synergian/wagon-git
https://jeroenmols.com/blog/2016/02/05/wagongit/
http://kodbiro.com/use-github-pages-as-your-own-maven-repository/
http://downright-amazed.blogspot.com/2011/09/hosting-maven-repository-on-github-for.html
The upload of the AAR to the maven repository (hosted in our gitlab) requires the following dependency: `maven { url "https://raw.github.com/synergian/wagon-git/releases"}`
\ No newline at end of file
// Project information
buildDir = 'bin'
def getPackageName() {
return "org.linphone"
}
def firebaseEnable() {
File googleFile = new File('google-services.json')
return googleFile.exists()
}
buildscript {
File googleFile = new File('google-services.json')
repositories {
jcenter()
mavenCentral()
mavenLocal()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.0'
if (googleFile.exists()) {
classpath 'com.google.gms:google-services:3.1.0'
}
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
mavenLocal()
google()
maven{
url "https://gitlab.linphone.org/BC/public/maven_repository/raw/master"
}
}
}
apply plugin: 'com.android.application'
dependencies {
androidTestImplementation('com.android.support.test.espresso:espresso-core:+') {
exclude module: 'support-annotations'
}
androidTestImplementation 'com.jayway.android.robotium:robotium-solo:5.6.3'
androidTestImplementation 'junit:junit:4.12'
implementation 'org.apache.commons:commons-compress:1.16.1'
if (firebaseEnable()) {
implementation 'com.google.firebase:firebase-messaging:15.0.2'
}
implementation 'com.android.support:support-v4:27.0.1'
// implementation project(':liblinphone-sdk')
// releaseImplementation 'org.linphone:liblinphone-sdk:4.0.1'
debugImplementation 'org.linphone:liblinphone-sdk:4.0.1-DEBUG'
}
if (firebaseEnable()) {
apply plugin: 'com.google.gms.google-services'
}
///// Exclude Files /////
def excludeFiles = []
// Exclude firebase file if not enable
if (!firebaseEnable()) {
excludeFiles.add('**/Firebase*')
println '[Push Notification] Firebase disabled'
} else {
excludeFiles.add('**/gcm*')
println '[Push Notification] Firebase enabled'
}
excludeFiles.add('src/android/org/linphone/tutorials/*.java')
def excludePackage = []
excludePackage.add('**/gdb.*')
excludePackage.add('**/libopenh264**')
excludePackage.add('**/**tester**')
excludePackage.add('**/LICENSE.txt')
/////////////////////////
android {
defaultConfig {
compileSdkVersion 28
buildToolsVersion "28.0.0"
applicationId getPackageName()
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
disable 'MissingTranslation', 'UnusedResources'
}
// Signing
signingConfigs {
release {
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
packaged {
initWith release
signingConfig null
matchingFallbacks = ['debug', 'release']
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
def srcDirs = ['src/android']
java.srcDirs = srcDirs
resources.srcDirs = srcDirs
aidl.srcDirs = srcDirs
renderscript.srcDirs = srcDirs
res.srcDirs = ['res']
assets.srcDirs = ['assets']
java.excludes = excludeFiles
// Exclude some useless files
packagingOptions {
excludes = excludePackage
}
}
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
sourceSets {
androidTest {
manifest.srcFile 'AndroidManifest.xml'
def srcDirs = ['src/android', 'src/androidTest']
java.srcDirs = srcDirs
resources.srcDirs = srcDirs
aidl.srcDirs = srcDirs
renderscript.srcDirs = srcDirs
res.srcDirs = ['res']
assets.srcDirs = ['assets']
java.excludes = excludeFiles
// Exclude some useless files
packagingOptions {
excludes = excludePackage
}
}
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
packagingOptions {
pickFirst 'META-INF/NOTICE'
pickFirst 'META-INF/LICENSE'
exclude 'META-INF/MANIFEST.MF'
}
}
// Grant permissions
android.applicationVariants.all { variant ->
def applicationId = getPackageName()
def adb = android.getAdbExecutable().toString()
def variantName = variant.name.capitalize()
def grantPermissionTask = tasks.create("grant${variantName}Permissions").doLast({
"${adb} devices".execute().text.eachLine {
"${adb} shell pm grant ${applicationId} android.permission.RECORD_AUDIO".execute()
"${adb} shell pm grant ${applicationId} android.permission.WRITE_EXTERNAL_STORAGE".execute()
"${adb} shell pm grant ${applicationId} android.permission.CAMERA".execute()
"${adb} shell pm grant ${applicationId} android.permission.READ_PHONE_STATE".execute()
"${adb} shell pm grant ${applicationId} android.permission.READ_CONTACTS".execute()
"${adb} shell pm grant ${applicationId} android.permission.WRITE_CONTACTS".execute()
}
})
}
task runApplication {
doLast {
def result = exec {
executable = android.getAdbExecutable().toString()
ignoreExitValue true
args = ['shell', 'monkey', '-p', getPackageName(), '-c', 'android.intent.category.LAUNCHER', '1']
}
}
}
// Project information
buildDir = 'bin'
buildscript {
repositories {
jcenter()
mavenCentral()
mavenLocal()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.0'
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
mavenLocal()
google()
maven { url "https://raw.github.com/synergian/wagon-git/releases"}
}
}
configurations {
javadocDeps
deployerJars
}
apply plugin: 'com.android.library'
apply plugin: 'maven'
dependencies {
implementation 'org.apache.commons:commons-compress:1.16.1'
javadocDeps 'org.apache.commons:commons-compress:1.16.1'
deployerJars "ar.com.synergian:wagon-git:0.2.5"
}
def srcDir = ['../submodules/mediastreamer2/java/src']
def rootSdk
if (file('android-arm64/share/linphonej/java/org/linphone/core/Factory.java').exists() )
rootSdk = 'android-arm64'
else if (file('android-arm/share/linphonej/java/org/linphone/core/Factory.java').exists() )
rootSdk = 'android-arm'
else if (file('android-armv7/share/linphonej/java/org/linphone/core/Factory.java').exists() )
rootSdk = 'android-armv7'
else if (file('android-x86/share/linphonej/java/org/linphone/core/Factory.java').exists() )
rootSdk = 'android-x86'
else {
println ("native sdk not ready yet")
rootSdk = ""
}
srcDir += [rootSdk+'/share/linphonej/java/org/linphone/core/']
srcDir += ['../submodules/linphone/wrappers/java/classes/']
def excludePackage = []
excludePackage.add('**/gdb.*')
excludePackage.add('**/libopenh264**')
excludePackage.add('**/**tester**')
excludePackage.add('**/LICENSE.txt')
android {
buildTypes {
release {
}
debug {
}
}
defaultConfig {
compileSdkVersion 28
buildToolsVersion "28.0.0"
multiDexEnabled true
setProperty("archivesBaseName", "liblinphone-sdk")
}
// Signing
signingConfigs {
release {
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
packaged {
initWith release
signingConfig null
//matchingFallbacks = ['debug', 'release']
}
}
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
sourceSets {
main {
manifest.srcFile 'AndroidManifestLibrary.xml'
java.srcDirs = srcDir
aidl.srcDirs = srcDir
assets.srcDirs = ["${buildDir}/sdk-assets/assets/"]
renderscript.srcDirs = srcDir
jniLibs.srcDirs = ['../libs']
java.excludes = ['**/mediastream/MediastreamerActivity.java']
// Exclude some useless files
packagingOptions {
excludes = excludePackage
}
}
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
}
///////////// Task /////////////
uploadArchives {
repositories {
mavenDeployer {
configuration = configurations.deployerJars
repository(url: 'git:master://git@gitlab.linphone.org:BC/public/maven_repository.git'){
authentication(privateKey: privateKey)
}
pom.project {
groupId 'org.linphone'
artifactId 'liblinphone-sdk'
version project.hasProperty("debug") ? "4.0.1-DEBUG": "4.0.1"
}
}
}
}
task(releaseJavadoc, type: Javadoc, dependsOn: "assembleRelease") {
source = srcDir
excludes = ['**/mediastream/MediastreamerActivity.java',
'**/**.html',
'**/**.aidl']
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += files(android.libraryVariants.release.javaCompile.classpath.files)
classpath += configurations.javadocDeps
options.encoding = 'UTF-8'
}
task sourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
task androidJavadocsJar(type: Jar, dependsOn: releaseJavadoc) {
classifier = 'javadoc'
from releaseJavadoc.destinationDir
}
task sdkZip(type: Zip) {
String appName = "liblinphone-android-sdk"
String gitSha = 'git describe --always'.execute().text.trim()
String newSdkName = appName + "-" + gitSha + ".zip"
from('bin/libs',
'bin/outputs/aar')
include '*'
archiveName newSdkName
}
task copyAssets(type: Sync) {
from rootSdk
into "${buildDir}/sdk-assets/assets/org.linphone.core"
include '**/*.png'
include '**/*.pem'
include '**/*.mkv'
include '**/*.wav'
include '**/*_grammar'
//rename '(.*)', '$1'.toLowerCase()
eachFile {
path = path.toLowerCase() //to workaround case insensitive fs (macosx)
println("Syncing sdk asset ${sourcePath} to ${path}")
}
doFirst {
println("Syncing sdk assets into root dir ${destinationDir}")
}
// do not copy those
includeEmptyDirs = false
}
project.tasks['preBuild'].dependsOn 'copyAssets'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment