SlideShare a Scribd company logo
Native Payment - Part II
In this section we’ll focus on the native dependencies before reviewing the implementation. Most native code requires that we link against specific libraries and this is
often the most challenging part of implementing the actual native interface
Implementation
✦ Before we go to actually implementing the native
interface we need to include the native libraries
✦ This posed two problems in both iOS and Android!
© Codename One 2017 all rights reserved
dependencies {
compile 'com.braintreepayments.api:drop-in:3.+'
}
If we review the braintree setup guide for Android we’ll see that the instructions include a gradle dependency change. This is a common tool for integrating 3rd party
libraries to Android native apps. and it usually follows syntax like the one we see above. Normally this is pretty easy to integrate…
Adding Dependencies
✦ The gradle dependency is pretty easy to add on
Android just add the build hint:
© Codename One 2017 all rights reserved
android.gradleDep=compile 'com.braintreepayments.api:drop-in:3.+'
The build hint android gradleDep should solve the problem in no time…
Executing: /home/ec2-user/android-sdk/tools/android create project --target android-23 --name MyRestaurant --path /tmp/build4055552516296801178xxx/MyRestaurant --activity MyRestaurantStub --package com.myrestaurant.app --gradle --gradle-version 2.0.0 Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/java
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/java/com/myrestaurant/app
Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/main/java/com/myrestaurant/app/MyRestaurantStub.java
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/androidTest/java
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/androidTest/java/com/myrestaurant/app
Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/androidTest/java/com/myrestaurant/app/MyRestaurantStubTest.java
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/values
Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/values/strings.xml
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/layout
Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/layout/main.xml
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/drawable-xhdpi
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/drawable-hdpi
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/drawable-mdpi
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/drawable-ldpi
Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/main/AndroidManifest.xml
Added file /tmp/build4055552516296801178xxx/MyRestaurant/build.gradle
Created directory /tmp/build4055552516296801178xxx/MyRestaurant/gradle/wrapper
Executing: /home/ec2-user/jdk1.8.0_45/bin/java -Dretrolambda.inputDir=/tmp/build4055552516296801178xxx/Classes -Dretrolambda.classpath=/tmp/build4055552516296801178xxx/Classes:/tmp/temp3492226097072112212.jar -Dretrolambda.outputDir=/tmp/build4055552516296801178xxx/Classes_retrolamda -Dretrolambda.bytecodeVersion=49 -Dretrolambda.defaultMethods=true -jar /tmp/temp5691500038666662080.jar Retrolambda 2.0.3
Bytecode version: 49 (Java 5)
Default methods: true
Input directory: /tmp/build4055552516296801178xxx/Classes
Output directory: /tmp/build4055552516296801178xxx/Classes_retrolamda
Classpath: /tmp/build4055552516296801178xxx/Classes:/tmp/temp3492226097072112212.jar
Saving lambda class: com/myrestaurant/app/ui/ContactUsForm$$Lambda$1
Saving lambda class: com/myrestaurant/app/ui/ContactUsForm$$Lambda$3
Saving lambda class: com/myrestaurant/app/ui/DishViewForm$$Lambda$1
Saving lambda class: com/myrestaurant/app/ui/DishViewForm$$Lambda$2
Saving lambda class: com/myrestaurant/app/ui/DishViewForm$$Lambda$3
Saving lambda class: com/myrestaurant/app/ui/CheckoutForm$$Lambda$1
Saving lambda class: com/myrestaurant/app/ui/CheckoutForm$$Lambda$2
Saving lambda class: com/myrestaurant/app/ui/CheckoutForm$$Lambda$3
Saving lambda class: com/myrestaurant/app/ui/CheckoutForm$$Lambda$4
Saving lambda class: com/myrestaurant/app/ui/MainMenuForm$$Lambda$1
Saving lambda class: com/myrestaurant/app/ui/MainMenuForm$$Lambda$2
Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$1
Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$2
Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$3
Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$4
Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$5
Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$6
Saving lambda class: com/myrestaurant/app/payment/Purchase$$Lambda$1
Generated manifest file: <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myrestaurant.app"
android:versionCode="100"
android:versionName="1.0"
xmlns:tools="http://schemas.android.com/tools"
android:minSdkVersion="15"
android:installLocation="auto">
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="23" />
<supports-screens android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true" />
<application android:label="MyRestaurant" android:icon="@drawable/icon" android:allowBackup="true" >
<activity android:name="MyRestaurantStub"
android:theme="@style/CustomTheme"
android:configChanges="orientation|keyboardHidden|screenSize"
android:launchMode="singleTop"
android:label="MyRestaurant">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.codename1.impl.android.LocalNotificationPublisher" ></receiver>
<service android:name="com.codename1.impl.android.BackgroundFetchHandler" android:exported="false" />
<activity android:name="com.codename1.impl.android.CodenameOneBackgroundFetchActivity" android:theme="@android:style/Theme.NoDisplay" />
<activity android:name="com.codename1.location.CodenameOneBackgroundLocationActivity" android:theme="@android:style/Theme.NoDisplay" />
<service android:name="com.codename1.location.BackgroundLocationHandler" android:exported="false" />
<service android:name="com.codename1.location.GeofenceHandler" android:exported="false" />
<service android:name="com.codename1.media.AudioService" android:exported="false" /> </application>
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.telephony" android:required="false" />
<uses-permission android:name="android.permission.INTERNET" android:required="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="false" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:required="false" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:required="false" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" android:required="false" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/><uses-feature android:glEsVersion="0x00020000" android:required="true"/></manifest>
Executing: /home/ec2-user/android/gradle-2.11/bin/gradle assembleRelease --no-daemon --stacktrace --info To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/2.11/userguide/gradle_daemon.html.
Starting daemon process: workingDir = /home/ec2-user/.gradle/daemon/2.11, daemonArgs: [/home/ec2-user/jdk1.8.0_45/bin/java, -XX:MaxPermSize=512m, -XX:+HeapDumpOnOutOfMemoryError, -Xmx2048m, -Dfile.encoding=UTF-8, -Duser.country=US, -Duser.language=en, -Duser.variant, -cp, /home/ec2-user/android/gradle-2.11/lib/gradle-launcher-2.11.jar, org.gradle.launcher.daemon.bootstrap.GradleDaemon, 2.11]
Starting process 'Gradle build daemon'. Working directory: /home/ec2-user/.gradle/daemon/2.11 Command: /home/ec2-user/jdk1.8.0_45/bin/java -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -cp /home/ec2-user/android/gradle-2.11/lib/gradle-launcher-2.11.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 2.11
Successfully started process 'Gradle build daemon'
An attempt to start the daemon took 0.765 secs.
Connected to daemon DaemonInfo{pid=26526, address=[596c13ab-cfa4-467a-8efc-90260f88ca54 port:34635, addresses:[/0:0:0:0:0:0:0:1%lo, /127.0.0.1]], idle=false, context=DefaultDaemonContext[uid=78c171cf-83fe-4135-a0c1-201b15b3bd4e,javaHome=/home/ec2-user/jdk1.8.0_45,daemonRegistryDir=/home/ec2-user/.gradle/daemon,pid=26526,idleTimeout=120000,daemonOpts=-XX:MaxPermSize=512m,-XX:+HeapDumpOnOutOfMemoryError,-Xmx2048m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]}. Dispatching request
BuildAndStop{id=5c72492d-eba2-4db6-81b4-b1e1f250ca35.1, currentDir=/tmp/build4055552516296801178xxx/MyRestaurant}.
Received result org.gradle.launcher.daemon.protocol.BuildStarted@d554c5f from daemon DaemonInfo{pid=26526, address=[596c13ab-cfa4-467a-8efc-90260f88ca54 port:34635, addresses:[/0:0:0:0:0:0:0:1%lo, /127.0.0.1]], idle=false, context=DefaultDaemonContext[uid=78c171cf-83fe-4135-a0c1-201b15b3bd4e,javaHome=/home/ec2-user/jdk1.8.0_45,daemonRegistryDir=/home/ec2-user/.gradle/daemon,pid=26526,idleTimeout=120000,daemonOpts=-XX:MaxPermSize=512m,-XX:+HeapDumpOnOutOfMemoryError,-Xmx2048m,-Dfile.encoding=UTF-8,-Duser.country=US,-
Duser.language=en,-Duser.variant]} (build should be starting).
The client will now receive all logging from the daemon (pid: 26526). The daemon log file: /home/ec2-user/.gradle/daemon/2.11/daemon-26526.out.log
Executing build with daemon context: DefaultDaemonContext[uid=78c171cf-83fe-4135-a0c1-201b15b3bd4e,javaHome=/home/ec2-user/jdk1.8.0_45,daemonRegistryDir=/home/ec2-user/.gradle/daemon,pid=26526,idleTimeout=120000,daemonOpts=-XX:MaxPermSize=512m,-XX:+HeapDumpOnOutOfMemoryError,-Xmx2048m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]
Starting Build
Settings evaluated using settings file '/master/settings.gradle'.
Projects loaded. Root project using build file '/tmp/build4055552516296801178xxx/MyRestaurant/build.gradle'.
Included projects: [root project 'MyRestaurant']
Evaluating root project 'MyRestaurant' using build file '/tmp/build4055552516296801178xxx/MyRestaurant/build.gradle'.
Compiling build file '/tmp/build4055552516296801178xxx/MyRestaurant/build.gradle' using SubsetScriptTransformer.
Compiling build file '/tmp/build4055552516296801178xxx/MyRestaurant/build.gradle' using BuildScriptTransformer.
Creating configuration compile
Creating configuration apk
Creating configuration provided
Creating configuration wearApp
Creating configuration androidTestCompile
Creating configuration androidTestApk
Creating configuration androidTestProvided
Creating configuration androidTestWearApp
Creating configuration testCompile
Creating configuration testApk
Creating configuration testProvided
Creating configuration testWearApp
Creating configuration debugCompile
Creating configuration debugApk
Creating configuration debugProvided
Creating configuration debugWearApp
Creating configuration testDebugCompile
Creating configuration testDebugApk
Creating configuration testDebugProvided
Creating configuration testDebugWearApp
Creating configuration releaseCompile
Creating configuration releaseApk
Creating configuration releaseProvided
Creating configuration releaseWearApp
Creating configuration testReleaseCompile
Creating configuration testReleaseApk
Creating configuration testReleaseProvided
Creating configuration testReleaseWearApp
Parsing the SDK, no caching allowed
Parsing /home/ec2-user/android-sdk/build-tools/19.0.3/package.xml
Parsing /home/ec2-user/android-sdk/build-tools/22.0.1/package.xml
First Error
But if we try to build the app we’ll get this build error which is not just unreadable it’s also snipped because it overflows the screen…
Merging manifest with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:2:1-29:12
Merging uses-sdk with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:8:5-10:41
Merging uses-permission#android.permission.ACCESS_NETWORK_STATE with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:12:5-79
Merging uses-permission#android.permission.INTERNET with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:13:5-67
Merging application with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:15:5-27:19
Merging result:ERROR
/tmp/build4055552516296801178xxx/MyRestaurant/src/main/AndroidManifest.xml:9:5-75 Error:
uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/com.braintreepayments.api/drop-in/3.0.7/AndroidManifest.xml
Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage
See http://g.co/androidstudio/manifest-merger for more information about the manifest merger.
:processReleaseManifest FAILED
:processReleaseManifest (Thread[Daemon worker,5,main]) completed. Took 0.261 secs.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':processReleaseManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/com.braintreepayments.api/drop-in/3.0.7/AndroidManifest.xml
Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage
* Try:
Run with --debug option to get more log output.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':processReleaseManifest'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154)
at org.gradle.internal.Factories$1.create(Factories.java:22)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)
at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)
at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:45)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:40)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: java.lang.RuntimeException: Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/com.braintreepayments.api/drop-in/3.0.7/AndroidManifest.xml
Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage
at com.android.builder.core.AndroidBuilder.mergeManifests(AndroidBuilder.java:686)
at com.android.build.gradle.tasks.MergeManifests.doFullTaskAction(MergeManifests.java:65)
at com.android.build.gradle.internal.tasks.IncrementalTask.taskAction(IncrementalTask.java:82)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:244)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:231)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
... 68 more
BUILD FAILED
Total time: 18.321 secs
Stopped 0 compiler daemon(s).
Received result Failure[value=org.gradle.initialization.ReportedException: org.gradle.internal.exceptions.LocationAwareException: Execution failed for task ':processReleaseManifest'.] from daemon DaemonInfo{pid=26526, address=[596c13ab-cfa4-467a-8efc-90260f88ca54 port:34635, addresses:[/0:0:0:0:0:0:0:1%lo, /127.0.0.1]], idle=false, context=DefaultDaemonContext[uid=78c171cf-83fe-4135-a0c1-201b15b3bd4e,javaHome=/home/ec2-user/
First Error - a bit less…
So let’s zoom in a bit but this doesn’t tell us more. One of the mistakes people make when looking at the gradle errors is the focus on the gradle exceptions which are
confusing and verbose. The error is usually printed above that
Merging manifest with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:2:1-29:12
Merging uses-sdk with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:8:5-10:41
Merging uses-permission#android.permission.ACCESS_NETWORK_STATE with lower [com.braintreepayments.api:drop-in:3.0.7]
AndroidManifest.xml:12:5-79
Merging uses-permission#android.permission.INTERNET with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:
13:5-67
Merging application with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:15:5-27:19
Merging result:ERROR
/tmp/build4055552516296801178xxx/MyRestaurant/src/main/AndroidManifest.xml:9:5-75 Error:
uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/
build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/com.braintreepayments.api/drop-in/3.0.7/
AndroidManifest.xml
Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage
See http://g.co/androidstudio/manifest-merger for more information about the manifest merger.
:processReleaseManifest FAILED
:processReleaseManifest (Thread[Daemon worker,5,main]) completed. Took 0.261 secs.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':processReleaseManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library
[com.braintreepayments.api:drop-in:3.0.7] /tmp/build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/
com.braintreepayments.api/drop-in/3.0.7/AndroidManifest.xml
Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage
* Try:
Run with --debug option to get more log output.
* Exception is:
First Error - Ugh…
And here it is in bold. The minSdkVersion is the actual error we are experiencing. The problem is that the suggestion entry is wrong we can just fix our min SDK version in
Codename One instead…
Bad Suggestion
✦ The gradle build error suggested a hack instead we
can just increase the min sdk version with the build
hint:
© Codename One 2017 all rights reserved
android.min_sdk_version=16
We have a build hint for setting the Android min sdk version to 16 which will align it with the min sdk version required by braintree.
/tmp/build1964575092214819498xxx/MyRestaurant/build/intermediates/res/merged/release/values-
v24/values-v24.xml:3: AAPT: Error retrieving parent for item: No resource found that matches
the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.
/tmp/build1964575092214819498xxx/MyRestaurant/build/intermediates/res/merged/release/values-
v24/values-v24.xml:4: AAPT: Error retrieving parent for item: No resource found that matches
the given name 'android:TextAppearance.Material.Widget.Button.Colored'.
:processReleaseResources FAILED
:processReleaseResources (Thread[Daemon worker,5,main]) completed. Took 0.41 secs.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':processReleaseResources'.
> com.android.ide.common.process.ProcessException:
org.gradle.process.internal.ExecException: Process 'command '/home/ec2-user/android-sdk/
build-tools/23.0.1/aapt'' finished with non-zero exit value 1
* Try:
Run with --debug option to get more log output.
Second Error - (trimmed)
WTF
I try to keep my cool but seriously?

Luckily google search found this:
http://stackoverflow.com/questions/
32075498/error-retrieving-parent-for-
item-no-resource-found-that-matches-
the-given-name
The problem is that even after that change I still got a compilation error which was just about the most unclear error message possible!

I googled this which is pretty much the best way to solve issues like this and I found a stack overflow entry that explained that this is caused by the wrong SDK version
setting in Android.
Setting the SDK Version
✦ That annoying error can be solved by setting the
SDK version which defaults to 23
© Codename One 2017 all rights reserved
android.sdkVersion=25
At this time Codename One defaults to SDK 23, notice we update that value occasionally so this might be incorrect when you see this. However, in this particular case
the fix was simple set the sdk version to 25.

Once this was set build went thru as expected and we were able to get a working project for Android
On iOS things weren’t as bad
✦ iOS can be setup thru cocoapods which work really
well with Codename One. We already use
cocoapods in the project for the GoogleMaps
support:
© Codename One 2017 all rights reserved
ios.pods=BraintreeDropIn,GoogleMaps
On the iOS side things were also a bit tricky. iOS has a tool called cocoapods which allows us to define dependencies. Since we already use the maps in the contact us
form we already have a dependency on that. We can just add the braintree drop in dependency as explained in the integration guide in the braintree site and this should
work.
Problem
© Codename One 2017 all rights reserved
However, it seems that drop in requires iOS 9+ as highlighted in their site…
No Problem
© Codename One 2017 all rights reserved
ios.pods.platform=9.0
So we can define the build hint pods platform to force the minimal platform.
Compilation Error
✦ The Google Maps lib defines this value as 7.0 and
we have a conflict…
✦ We’ll fix that in a coming update but for now I just
edited the file
codenameone_library_required.properties in
GoogleMaps.cn1lib and removed the line
© Codename One 2017 all rights reserved
codename1.arg.ios.pods.platform=7.0
But this created a conflict with the Google Maps cn1lib which defined the pods platform to 7.0. This is something that should be resolved by now but if you happen to
run into something like this and need to fix it at this exact moment then what I did is simple. I edited the required properties in the cn1lib file and just removed the
offending line.

Notice that a cn1lib is just a zip file so I was able to just edit the properties file.

More Related Content

PPT
CICON2010: Adam Griffiths - CodeIgniter 2
PDF
Building Mobile Friendly APIs in Rails
PDF
Symfony2 for Midgard Developers
PDF
Introduction to Magento 2 module development - PHP Antwerp Meetup 2017
PPTX
Sst hackathon express
PDF
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
PDF
Porting Rails Apps to High Availability Systems
PDF
Hacking the Codename One Source Code - Part IV - Transcript.pdf
CICON2010: Adam Griffiths - CodeIgniter 2
Building Mobile Friendly APIs in Rails
Symfony2 for Midgard Developers
Introduction to Magento 2 module development - PHP Antwerp Meetup 2017
Sst hackathon express
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
Porting Rails Apps to High Availability Systems
Hacking the Codename One Source Code - Part IV - Transcript.pdf

Similar to Native Payment - Part 2 - Transcript.pdf (20)

PPTX
A peek into the world of WordPress plugin development
PDF
React Native +Redux + ES6 (Updated)
PDF
Tips & Tricks Android
PDF
Frontend Monoliths: Run if you can!
PPT
Demystifying Maven
ZIP
Renegades Guide to Hacking Rails Internals
PDF
Large Scale Apps With Vue 3 And Typescript Damiano Fusco
PPTX
Aleksandr Kutsan "Managing Dependencies in C++"
PDF
Serverless, The Middy Way - Workshop
PDF
Build a notepad application with PHP, MongoDB, and IBM Bluemix - by Vikram Va...
PDF
7 Ways to improve your gradle build
PPTX
Hands on the gradle
PDF
React Lifecycle and Reconciliation
PDF
C 10 Pocket Reference Instant Help For C 10 Programmers First Early Release 1...
PDF
Remote Config REST API and Versioning
PPT
Red5 - PHUG Workshops
KEY
Código Saudável => Programador Feliz - Rs on Rails 2010
PDF
Some tips to improve developer experience with Symfony
KEY
Ruby For Startups
PDF
Patch File.pdf
A peek into the world of WordPress plugin development
React Native +Redux + ES6 (Updated)
Tips & Tricks Android
Frontend Monoliths: Run if you can!
Demystifying Maven
Renegades Guide to Hacking Rails Internals
Large Scale Apps With Vue 3 And Typescript Damiano Fusco
Aleksandr Kutsan "Managing Dependencies in C++"
Serverless, The Middy Way - Workshop
Build a notepad application with PHP, MongoDB, and IBM Bluemix - by Vikram Va...
7 Ways to improve your gradle build
Hands on the gradle
React Lifecycle and Reconciliation
C 10 Pocket Reference Instant Help For C 10 Programmers First Early Release 1...
Remote Config REST API and Versioning
Red5 - PHUG Workshops
Código Saudável => Programador Feliz - Rs on Rails 2010
Some tips to improve developer experience with Symfony
Ruby For Startups
Patch File.pdf

More from ShaiAlmog1 (20)

PDF
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
PDF
create-netflix-clone-06-client-ui.pdf
PDF
create-netflix-clone-01-introduction_transcript.pdf
PDF
create-netflix-clone-02-server_transcript.pdf
PDF
create-netflix-clone-04-server-continued_transcript.pdf
PDF
create-netflix-clone-01-introduction.pdf
PDF
create-netflix-clone-06-client-ui_transcript.pdf
PDF
create-netflix-clone-03-server.pdf
PDF
create-netflix-clone-04-server-continued.pdf
PDF
create-netflix-clone-05-client-model_transcript.pdf
PDF
create-netflix-clone-03-server_transcript.pdf
PDF
create-netflix-clone-02-server.pdf
PDF
create-netflix-clone-05-client-model.pdf
PDF
Creating a Whatsapp Clone - Part II.pdf
PDF
Creating a Whatsapp Clone - Part IX - Transcript.pdf
PDF
Creating a Whatsapp Clone - Part II - Transcript.pdf
PDF
Creating a Whatsapp Clone - Part V - Transcript.pdf
PDF
Creating a Whatsapp Clone - Part IV - Transcript.pdf
PDF
Creating a Whatsapp Clone - Part IV.pdf
PDF
Creating a Whatsapp Clone - Part I - Transcript.pdf
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-01-introduction.pdf
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-03-server.pdf
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-02-server.pdf
create-netflix-clone-05-client-model.pdf
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf

Recently uploaded (20)

PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
Machine Learning_overview_presentation.pptx
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Approach and Philosophy of On baking technology
PDF
Mushroom cultivation and it's methods.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Getting Started with Data Integration: FME Form 101
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
Tartificialntelligence_presentation.pptx
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPT
Teaching material agriculture food technology
PPTX
Spectroscopy.pptx food analysis technology
Advanced methodologies resolving dimensionality complications for autism neur...
Machine Learning_overview_presentation.pptx
NewMind AI Weekly Chronicles - August'25-Week II
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Approach and Philosophy of On baking technology
Mushroom cultivation and it's methods.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Accuracy of neural networks in brain wave diagnosis of schizophrenia
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Getting Started with Data Integration: FME Form 101
Assigned Numbers - 2025 - Bluetooth® Document
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Programs and apps: productivity, graphics, security and other tools
Tartificialntelligence_presentation.pptx
Reach Out and Touch Someone: Haptics and Empathic Computing
Teaching material agriculture food technology
Spectroscopy.pptx food analysis technology

Native Payment - Part 2 - Transcript.pdf

  • 1. Native Payment - Part II In this section we’ll focus on the native dependencies before reviewing the implementation. Most native code requires that we link against specific libraries and this is often the most challenging part of implementing the actual native interface
  • 2. Implementation ✦ Before we go to actually implementing the native interface we need to include the native libraries ✦ This posed two problems in both iOS and Android! © Codename One 2017 all rights reserved dependencies { compile 'com.braintreepayments.api:drop-in:3.+' } If we review the braintree setup guide for Android we’ll see that the instructions include a gradle dependency change. This is a common tool for integrating 3rd party libraries to Android native apps. and it usually follows syntax like the one we see above. Normally this is pretty easy to integrate…
  • 3. Adding Dependencies ✦ The gradle dependency is pretty easy to add on Android just add the build hint: © Codename One 2017 all rights reserved android.gradleDep=compile 'com.braintreepayments.api:drop-in:3.+' The build hint android gradleDep should solve the problem in no time…
  • 4. Executing: /home/ec2-user/android-sdk/tools/android create project --target android-23 --name MyRestaurant --path /tmp/build4055552516296801178xxx/MyRestaurant --activity MyRestaurantStub --package com.myrestaurant.app --gradle --gradle-version 2.0.0 Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/java Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/java/com/myrestaurant/app Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/main/java/com/myrestaurant/app/MyRestaurantStub.java Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/androidTest/java Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/androidTest/java/com/myrestaurant/app Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/androidTest/java/com/myrestaurant/app/MyRestaurantStubTest.java Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/values Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/values/strings.xml Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/layout Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/layout/main.xml Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/drawable-xhdpi Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/drawable-hdpi Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/drawable-mdpi Created directory /tmp/build4055552516296801178xxx/MyRestaurant/src/main/res/drawable-ldpi Added file /tmp/build4055552516296801178xxx/MyRestaurant/src/main/AndroidManifest.xml Added file /tmp/build4055552516296801178xxx/MyRestaurant/build.gradle Created directory /tmp/build4055552516296801178xxx/MyRestaurant/gradle/wrapper Executing: /home/ec2-user/jdk1.8.0_45/bin/java -Dretrolambda.inputDir=/tmp/build4055552516296801178xxx/Classes -Dretrolambda.classpath=/tmp/build4055552516296801178xxx/Classes:/tmp/temp3492226097072112212.jar -Dretrolambda.outputDir=/tmp/build4055552516296801178xxx/Classes_retrolamda -Dretrolambda.bytecodeVersion=49 -Dretrolambda.defaultMethods=true -jar /tmp/temp5691500038666662080.jar Retrolambda 2.0.3 Bytecode version: 49 (Java 5) Default methods: true Input directory: /tmp/build4055552516296801178xxx/Classes Output directory: /tmp/build4055552516296801178xxx/Classes_retrolamda Classpath: /tmp/build4055552516296801178xxx/Classes:/tmp/temp3492226097072112212.jar Saving lambda class: com/myrestaurant/app/ui/ContactUsForm$$Lambda$1 Saving lambda class: com/myrestaurant/app/ui/ContactUsForm$$Lambda$3 Saving lambda class: com/myrestaurant/app/ui/DishViewForm$$Lambda$1 Saving lambda class: com/myrestaurant/app/ui/DishViewForm$$Lambda$2 Saving lambda class: com/myrestaurant/app/ui/DishViewForm$$Lambda$3 Saving lambda class: com/myrestaurant/app/ui/CheckoutForm$$Lambda$1 Saving lambda class: com/myrestaurant/app/ui/CheckoutForm$$Lambda$2 Saving lambda class: com/myrestaurant/app/ui/CheckoutForm$$Lambda$3 Saving lambda class: com/myrestaurant/app/ui/CheckoutForm$$Lambda$4 Saving lambda class: com/myrestaurant/app/ui/MainMenuForm$$Lambda$1 Saving lambda class: com/myrestaurant/app/ui/MainMenuForm$$Lambda$2 Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$1 Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$2 Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$3 Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$4 Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$5 Saving lambda class: com/myrestaurant/app/ui/BaseForm$$Lambda$6 Saving lambda class: com/myrestaurant/app/payment/Purchase$$Lambda$1 Generated manifest file: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.myrestaurant.app" android:versionCode="100" android:versionName="1.0" xmlns:tools="http://schemas.android.com/tools" android:minSdkVersion="15" android:installLocation="auto"> <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="23" /> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" /> <application android:label="MyRestaurant" android:icon="@drawable/icon" android:allowBackup="true" > <activity android:name="MyRestaurantStub" android:theme="@style/CustomTheme" android:configChanges="orientation|keyboardHidden|screenSize" android:launchMode="singleTop" android:label="MyRestaurant"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.codename1.impl.android.LocalNotificationPublisher" ></receiver> <service android:name="com.codename1.impl.android.BackgroundFetchHandler" android:exported="false" /> <activity android:name="com.codename1.impl.android.CodenameOneBackgroundFetchActivity" android:theme="@android:style/Theme.NoDisplay" /> <activity android:name="com.codename1.location.CodenameOneBackgroundLocationActivity" android:theme="@android:style/Theme.NoDisplay" /> <service android:name="com.codename1.location.BackgroundLocationHandler" android:exported="false" /> <service android:name="com.codename1.location.GeofenceHandler" android:exported="false" /> <service android:name="com.codename1.media.AudioService" android:exported="false" /> </application> <uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-feature android:name="android.hardware.telephony" android:required="false" /> <uses-permission android:name="android.permission.INTERNET" android:required="false" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="false" /> <uses-feature android:name="android.hardware.location" android:required="false" /> <uses-feature android:name="android.hardware.location.gps" android:required="false" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:required="false" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:required="false" /> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" android:required="false" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/><uses-feature android:glEsVersion="0x00020000" android:required="true"/></manifest> Executing: /home/ec2-user/android/gradle-2.11/bin/gradle assembleRelease --no-daemon --stacktrace --info To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/2.11/userguide/gradle_daemon.html. Starting daemon process: workingDir = /home/ec2-user/.gradle/daemon/2.11, daemonArgs: [/home/ec2-user/jdk1.8.0_45/bin/java, -XX:MaxPermSize=512m, -XX:+HeapDumpOnOutOfMemoryError, -Xmx2048m, -Dfile.encoding=UTF-8, -Duser.country=US, -Duser.language=en, -Duser.variant, -cp, /home/ec2-user/android/gradle-2.11/lib/gradle-launcher-2.11.jar, org.gradle.launcher.daemon.bootstrap.GradleDaemon, 2.11] Starting process 'Gradle build daemon'. Working directory: /home/ec2-user/.gradle/daemon/2.11 Command: /home/ec2-user/jdk1.8.0_45/bin/java -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -cp /home/ec2-user/android/gradle-2.11/lib/gradle-launcher-2.11.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 2.11 Successfully started process 'Gradle build daemon' An attempt to start the daemon took 0.765 secs. Connected to daemon DaemonInfo{pid=26526, address=[596c13ab-cfa4-467a-8efc-90260f88ca54 port:34635, addresses:[/0:0:0:0:0:0:0:1%lo, /127.0.0.1]], idle=false, context=DefaultDaemonContext[uid=78c171cf-83fe-4135-a0c1-201b15b3bd4e,javaHome=/home/ec2-user/jdk1.8.0_45,daemonRegistryDir=/home/ec2-user/.gradle/daemon,pid=26526,idleTimeout=120000,daemonOpts=-XX:MaxPermSize=512m,-XX:+HeapDumpOnOutOfMemoryError,-Xmx2048m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]}. Dispatching request BuildAndStop{id=5c72492d-eba2-4db6-81b4-b1e1f250ca35.1, currentDir=/tmp/build4055552516296801178xxx/MyRestaurant}. Received result org.gradle.launcher.daemon.protocol.BuildStarted@d554c5f from daemon DaemonInfo{pid=26526, address=[596c13ab-cfa4-467a-8efc-90260f88ca54 port:34635, addresses:[/0:0:0:0:0:0:0:1%lo, /127.0.0.1]], idle=false, context=DefaultDaemonContext[uid=78c171cf-83fe-4135-a0c1-201b15b3bd4e,javaHome=/home/ec2-user/jdk1.8.0_45,daemonRegistryDir=/home/ec2-user/.gradle/daemon,pid=26526,idleTimeout=120000,daemonOpts=-XX:MaxPermSize=512m,-XX:+HeapDumpOnOutOfMemoryError,-Xmx2048m,-Dfile.encoding=UTF-8,-Duser.country=US,- Duser.language=en,-Duser.variant]} (build should be starting). The client will now receive all logging from the daemon (pid: 26526). The daemon log file: /home/ec2-user/.gradle/daemon/2.11/daemon-26526.out.log Executing build with daemon context: DefaultDaemonContext[uid=78c171cf-83fe-4135-a0c1-201b15b3bd4e,javaHome=/home/ec2-user/jdk1.8.0_45,daemonRegistryDir=/home/ec2-user/.gradle/daemon,pid=26526,idleTimeout=120000,daemonOpts=-XX:MaxPermSize=512m,-XX:+HeapDumpOnOutOfMemoryError,-Xmx2048m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant] Starting Build Settings evaluated using settings file '/master/settings.gradle'. Projects loaded. Root project using build file '/tmp/build4055552516296801178xxx/MyRestaurant/build.gradle'. Included projects: [root project 'MyRestaurant'] Evaluating root project 'MyRestaurant' using build file '/tmp/build4055552516296801178xxx/MyRestaurant/build.gradle'. Compiling build file '/tmp/build4055552516296801178xxx/MyRestaurant/build.gradle' using SubsetScriptTransformer. Compiling build file '/tmp/build4055552516296801178xxx/MyRestaurant/build.gradle' using BuildScriptTransformer. Creating configuration compile Creating configuration apk Creating configuration provided Creating configuration wearApp Creating configuration androidTestCompile Creating configuration androidTestApk Creating configuration androidTestProvided Creating configuration androidTestWearApp Creating configuration testCompile Creating configuration testApk Creating configuration testProvided Creating configuration testWearApp Creating configuration debugCompile Creating configuration debugApk Creating configuration debugProvided Creating configuration debugWearApp Creating configuration testDebugCompile Creating configuration testDebugApk Creating configuration testDebugProvided Creating configuration testDebugWearApp Creating configuration releaseCompile Creating configuration releaseApk Creating configuration releaseProvided Creating configuration releaseWearApp Creating configuration testReleaseCompile Creating configuration testReleaseApk Creating configuration testReleaseProvided Creating configuration testReleaseWearApp Parsing the SDK, no caching allowed Parsing /home/ec2-user/android-sdk/build-tools/19.0.3/package.xml Parsing /home/ec2-user/android-sdk/build-tools/22.0.1/package.xml First Error But if we try to build the app we’ll get this build error which is not just unreadable it’s also snipped because it overflows the screen…
  • 5. Merging manifest with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:2:1-29:12 Merging uses-sdk with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:8:5-10:41 Merging uses-permission#android.permission.ACCESS_NETWORK_STATE with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:12:5-79 Merging uses-permission#android.permission.INTERNET with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:13:5-67 Merging application with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:15:5-27:19 Merging result:ERROR /tmp/build4055552516296801178xxx/MyRestaurant/src/main/AndroidManifest.xml:9:5-75 Error: uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/com.braintreepayments.api/drop-in/3.0.7/AndroidManifest.xml Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage See http://g.co/androidstudio/manifest-merger for more information about the manifest merger. :processReleaseManifest FAILED :processReleaseManifest (Thread[Daemon worker,5,main]) completed. Took 0.261 secs. FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':processReleaseManifest'. > Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/com.braintreepayments.api/drop-in/3.0.7/AndroidManifest.xml Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage * Try: Run with --debug option to get more log output. * Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':processReleaseManifest'. at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35) at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64) at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58) at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53) at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110) at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37) at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23) at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43) at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30) at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154) at org.gradle.internal.Factories$1.create(Factories.java:22) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52) at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151) at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32) at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99) at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62) at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93) at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82) at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94) at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28) at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28) at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75) at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:45) at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74) at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72) at org.gradle.util.Swapper.swap(Swapper.java:38) at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:40) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120) at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50) at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) Caused by: java.lang.RuntimeException: Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/com.braintreepayments.api/drop-in/3.0.7/AndroidManifest.xml Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage at com.android.builder.core.AndroidBuilder.mergeManifests(AndroidBuilder.java:686) at com.android.build.gradle.tasks.MergeManifests.doFullTaskAction(MergeManifests.java:65) at com.android.build.gradle.internal.tasks.IncrementalTask.taskAction(IncrementalTask.java:82) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:244) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:231) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61) ... 68 more BUILD FAILED Total time: 18.321 secs Stopped 0 compiler daemon(s). Received result Failure[value=org.gradle.initialization.ReportedException: org.gradle.internal.exceptions.LocationAwareException: Execution failed for task ':processReleaseManifest'.] from daemon DaemonInfo{pid=26526, address=[596c13ab-cfa4-467a-8efc-90260f88ca54 port:34635, addresses:[/0:0:0:0:0:0:0:1%lo, /127.0.0.1]], idle=false, context=DefaultDaemonContext[uid=78c171cf-83fe-4135-a0c1-201b15b3bd4e,javaHome=/home/ec2-user/ First Error - a bit less… So let’s zoom in a bit but this doesn’t tell us more. One of the mistakes people make when looking at the gradle errors is the focus on the gradle exceptions which are confusing and verbose. The error is usually printed above that
  • 6. Merging manifest with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:2:1-29:12 Merging uses-sdk with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:8:5-10:41 Merging uses-permission#android.permission.ACCESS_NETWORK_STATE with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:12:5-79 Merging uses-permission#android.permission.INTERNET with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml: 13:5-67 Merging application with lower [com.braintreepayments.api:drop-in:3.0.7] AndroidManifest.xml:15:5-27:19 Merging result:ERROR /tmp/build4055552516296801178xxx/MyRestaurant/src/main/AndroidManifest.xml:9:5-75 Error: uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/ build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/com.braintreepayments.api/drop-in/3.0.7/ AndroidManifest.xml Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage See http://g.co/androidstudio/manifest-merger for more information about the manifest merger. :processReleaseManifest FAILED :processReleaseManifest (Thread[Daemon worker,5,main]) completed. Took 0.261 secs. FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':processReleaseManifest'. > Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.braintreepayments.api:drop-in:3.0.7] /tmp/build4055552516296801178xxx/MyRestaurant/build/intermediates/exploded-aar/ com.braintreepayments.api/drop-in/3.0.7/AndroidManifest.xml Suggestion: use tools:overrideLibrary="com.braintreepayments.api.dropin" to force usage * Try: Run with --debug option to get more log output. * Exception is: First Error - Ugh… And here it is in bold. The minSdkVersion is the actual error we are experiencing. The problem is that the suggestion entry is wrong we can just fix our min SDK version in Codename One instead…
  • 7. Bad Suggestion ✦ The gradle build error suggested a hack instead we can just increase the min sdk version with the build hint: © Codename One 2017 all rights reserved android.min_sdk_version=16 We have a build hint for setting the Android min sdk version to 16 which will align it with the min sdk version required by braintree.
  • 8. /tmp/build1964575092214819498xxx/MyRestaurant/build/intermediates/res/merged/release/values- v24/values-v24.xml:3: AAPT: Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'. /tmp/build1964575092214819498xxx/MyRestaurant/build/intermediates/res/merged/release/values- v24/values-v24.xml:4: AAPT: Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Colored'. :processReleaseResources FAILED :processReleaseResources (Thread[Daemon worker,5,main]) completed. Took 0.41 secs. FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':processReleaseResources'. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/home/ec2-user/android-sdk/ build-tools/23.0.1/aapt'' finished with non-zero exit value 1 * Try: Run with --debug option to get more log output. Second Error - (trimmed) WTF I try to keep my cool but seriously?
 Luckily google search found this: http://stackoverflow.com/questions/ 32075498/error-retrieving-parent-for- item-no-resource-found-that-matches- the-given-name The problem is that even after that change I still got a compilation error which was just about the most unclear error message possible! I googled this which is pretty much the best way to solve issues like this and I found a stack overflow entry that explained that this is caused by the wrong SDK version setting in Android.
  • 9. Setting the SDK Version ✦ That annoying error can be solved by setting the SDK version which defaults to 23 © Codename One 2017 all rights reserved android.sdkVersion=25 At this time Codename One defaults to SDK 23, notice we update that value occasionally so this might be incorrect when you see this. However, in this particular case the fix was simple set the sdk version to 25. Once this was set build went thru as expected and we were able to get a working project for Android
  • 10. On iOS things weren’t as bad ✦ iOS can be setup thru cocoapods which work really well with Codename One. We already use cocoapods in the project for the GoogleMaps support: © Codename One 2017 all rights reserved ios.pods=BraintreeDropIn,GoogleMaps On the iOS side things were also a bit tricky. iOS has a tool called cocoapods which allows us to define dependencies. Since we already use the maps in the contact us form we already have a dependency on that. We can just add the braintree drop in dependency as explained in the integration guide in the braintree site and this should work.
  • 11. Problem © Codename One 2017 all rights reserved However, it seems that drop in requires iOS 9+ as highlighted in their site…
  • 12. No Problem © Codename One 2017 all rights reserved ios.pods.platform=9.0 So we can define the build hint pods platform to force the minimal platform.
  • 13. Compilation Error ✦ The Google Maps lib defines this value as 7.0 and we have a conflict… ✦ We’ll fix that in a coming update but for now I just edited the file codenameone_library_required.properties in GoogleMaps.cn1lib and removed the line © Codename One 2017 all rights reserved codename1.arg.ios.pods.platform=7.0 But this created a conflict with the Google Maps cn1lib which defined the pods platform to 7.0. This is something that should be resolved by now but if you happen to run into something like this and need to fix it at this exact moment then what I did is simple. I edited the required properties in the cn1lib file and just removed the offending line. Notice that a cn1lib is just a zip file so I was able to just edit the properties file.