Closed BartAdv closed 9 years ago
Thing is, Google APIs (such as Maps) indeed reside in add-ons
directory. GgPS for some reason are put into extra
. They need some special treatment, as they are not version-dependent. Also it seems that guidelines suggest to use it as a project dependency rather than a dependency JAR. Figuring out the correct way to handle this would be preferable before adding this functionality to lein-droid.
I'm also having some trouble integrating Google Play Services into my app, the main issue is that if i go the suggested route of the project dependency, then it requires a clojure project rather than a java project. Doing it the way @BartAdv describes using :external-classes-paths
leads to Dex running out of heap space. Any advice?
Dex is a hog, that's not unusual. On Jun 6, 2014 12:00 AM, "arundilipan" notifications@github.com wrote:
I'm also having some trouble integrating Google Play Services into my app, the main issue is that if i go the suggested route of the project dependency, then it requires a clojure project rather than a java project. Doing it the way @BartAdv https://github.com/BartAdv describes using :external-classes-paths leads to Dex running out of heap space. Any advice?
— Reply to this email directly or view it on GitHub https://github.com/clojure-android/lein-droid/issues/87#issuecomment-45303157 .
That's only part of the issue. I've been trying to get lein-droid to work with the google play services api, and it just will not work whatsoever. I've been hitting a brick wall for a while. I really need some help.
@arundilipan You can turn a Java project into a Clojure project by running lein droid init
inside Java project directory. I haven't done this for a while, so I'm not sure it still works, but you can try.
Also, have you uncommented the lines in project.clj
that increase the heap size for dexer? That usually solves the problem with OutOfMemory exception.
I'll tried changing the heap size and I ended up with too my references. I dunno what's going on.
I ended up with too my references
What do you mean?
It says that I have over 70000 references to the packages instead of the allowed 65535. I meant to say too many references.
Well yes, there is such problem. It can be possibly solved with incremental dexing, but there is no such functionality in lein-droid yet, and unfortunately I don't have time this summer to work on lein-droid.
Then how would I integrate the Google play services for ads?
You could try investigating the incremental dexing on your own, and try to perform it manually on the compiled classes. If you end up with something PR-looking, I will gladly merge it.
Is there any way I can use the library project in lein? If so how would I go about dealing with it?
I tried that, but the problem is that the library project isn't a leiningen project, that is, there is no project.clj
. Therefore adding the google play services to my :project-dependencies
fails. I tried the method of including the jar in my :external-classes-paths
, but that led to the error that I previously mentioned.
In the tutorial it is said to execute lein init
in the dependency project's directory first.
Running lein init
doesn't work. Lein doesn't have init command for some reason.
I managed to get around using admob, but I still need to use project dependencies. How long would dex take to compile my project? There is a noticeable difference in compile time with and without the project dependency. My project never gets to build with external dependncies. I would appreciate any help on the issue.
OK, I only tested project dependencies with ActionBarSherlock library and it worked. I don't know why dexing takes so much time, but I remember Zach once had a similar issue on Windows.
Can you check if there are many classes in dependency's target/
directory once you compile it?
I have nearly same problem...maybe.
I use GooglePlayService API for Admob and GoogleAnalytics. After variously tried, finally succeeded to use it...only debug build.
First, I tested building project with :use-google-api true
in my project.clj
, but that wasn't worked.
After some configuration, I found out that need to write dependency and some tricks.
ex) add keyword :project-dependencies
and :external-classes-paths
into :android
section on project.clj
like that:
:project-dependencies ["/opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib"]
:external-classes-paths ["/opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar"]
and need to put new project.clj
on directory that contains GooglePlayService API project in your AndroidSDK's extras/google/google_play_services/libproject/google-play-services_lib/
path, easy to make this using lein droid init
.
(defproject google-play-services_lib/google-play-services_lib "6.1.71-000"
:description "FIXME: Android library description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:min-lein-version "2.0.0"
:source-paths ["src/clojure" "src"]
:java-source-paths ["src/java" "gen"]
:javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]
:dependencies [[org.clojure-android/clojure "1.6.0-RC1"]
[neko/neko "3.0.1"]]
:android {:target-version "9"
:library true})
It works well on lain-droid 0.2.4
and debug build, but fails release build.
On some newer version of lain-droid
, need to use command lein with-profile release droid
for building release version.
It means that project need to have :build-type :release
element in profile's :android
section.
It seems there are no problems...really? Unfortunately answer is no. There were some problems that confuses me.
build-project-dependencies
function on lein-droid
ignores root project's profile.
If you use :project-dependencies
, it precedes dependencies profile than root project's profile.
Result, in spite of executing release build, it makes debug build.
And lein-droid
loses some settings like :sdk-path
, so build fails.
Of course, I might have a lot of mistakes.
(for example...my ${HOME}/.lein/profiles.clj
)
Please teach me if you have solutions.
Related to this, and I discovered other problems for building project. However, I didn't check on details yet, so I will make it clearly and create new issue.
All right... I think, this can be fixed by adding this to dependency project's project.clj
:
:profiles {:release {:build-type :release}}
The problem likely stems from the fact, that older lein-droid used just the current profile to determine whether the build is debug or release. Now it needs this field.
If this fix works, please create a new issue, and then I will fix lein droid init
template. You can see I haven't touched it in a while (the dependencies are outdated etc.)
I'm Sorry to kept you waiting.
added to dependency project's project.clj
:
:profiles {:release {:build-type :release}}
and build release.
$ DEBUG=1 lein with-profile release do clean, droid doall
output(some omitted, line "---"):
Leiningen's classpath: /home/yuta/.lein/self-installs/leiningen-2.5.0-standalone.jar
Applying task with-profile to [release do clean, droid doall]
Applying task do to (clean, droid doall)
Applying task clean to []
Applying task droid to [doall]
Building project dependency /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib ...
Generating manifest...
Generating R.java...
/opt/android-sdk/build-tools/21.1.1/aapt package --non-constant-id -f -m -M /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/AndroidManifest.xml -S /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/target/res -S /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/res -I /opt/android-sdk/platforms/android-9/android.jar -J /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/target/gen --generate-dependencies
Applying task javac to nil
Running javac with [-target 1.6 -source 1.6 -Xlint:-options @/tmp/.leiningen-cmdline5542040106851098650.tmp]
Compiling 1 source files to /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/target/classes
Applying task compile to nil
All namespaces already AOT compiled.
Running javac with [-target 1.6 -source 1.6 -Xlint:-options @/tmp/.leiningen-cmdline4268190429488884665.tmp]
Compiling 1 source files to /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/target/classes
Compiling Clojure files...
Project classpath: (/opt/android-sdk/tools/support/annotations.jar /opt/android-sdk/platforms/android-9/android.jar /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/test /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/src/clojure /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/src /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/dev-resources /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/resources /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/target/classes /home/yuta/.m2/repository/org/clojure-android/clojure/1.6.0-RC1/clojure-1.6.0-RC1.jar /home/yuta/.m2/repository/neko/neko/3.0.1/neko-3.0.1.jar /home/yuta/.m2/repository/org/clojure/tools.nrepl/0.2.6/tools.nrepl-0.2.6.jar /home/yuta/.m2/repository/clojure-complete/clojure-complete/0.2.3/clojure-complete-0.2.3.jar)
Build type: debug, dynamic compilation: enabled, remote REPL: enabled.
------------------------
Building dependency complete.
Generating manifest...
Generating R.java...
------------------------
Compiling 5 source files to /home/yuta/git/myproject/target/release/classes
Applying task compile to nil
All namespaces already AOT compiled.
Running javac with [-target 1.6 -source 1.6 -Xlint:-options @/tmp/.leiningen-cmdline3803311697534617080.tmp]
Compiling Clojure files...
Project classpath: (/opt/android-sdk/tools/support/annotations.jar /opt/android-sdk/platforms/android-15/android.jar /home/yuta/git/myproject/test /home/yuta/git/myproject/src/clojure /home/yuta/git/myproject/resources /home/yuta/git/myproject/target/release/classes /home/yuta/.m2/repository/neko/neko/3.0.2/neko-3.0.2.jar /home/yuta/.m2/repository/clj-time/clj-time/0.6.0/clj-time-0.6.0.jar /home/yuta/.m2/repository/joda-time/joda-time/2.2/joda-time-2.2.jar /home/yuta/.m2/repository/org/clojure-android/clojure/1.6.0-RC1/clojure-1.6.0-RC1.jar /home/yuta/.m2/repository/org/clojure/tools.nrepl/0.2.6/tools.nrepl-0.2.6.jar /home/yuta/.m2/repository/clojure-complete/clojure-complete/0.2.3/clojure-complete-0.2.3.jar /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/target/classes)
Build type: release, dynamic compilation: disabled, remote REPL: disabled.
Applying task javac to nil
Running javac with [-target 1.6 -source 1.6 -Xlint:-options @/tmp/.leiningen-cmdline2586393479411461558.tmp]
------------------------
Compilation succeeded.
Creating DEX....
------------------------
Creating APK...
------------------------
Installing APK...
------------------------
Success
Launching APK...
/opt/android-sdk/platform-tools/adb -s CB5125TPMG shell am start -n com.example.myproject/com.example.myproject.SplashActivity
Starting: Intent { cmp=com.example.myproject/.SplashActivity }
Binding device port 9999 to local port 9999 ...
/opt/android-sdk/platform-tools/adb -s CB5125TPMG forward tcp:9999 tcp:9999
Release build and install succeeded, but throws Exception when running.
12-01 00:57:04.267: E/AndroidRuntime(472): java.io.FileNotFoundException: Could not locate clojure/tools/nrepl/server__init.class or clojure/tools/nrepl/server.clj on classpath:
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.RT.load(RT.java:468)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.RT.load(RT.java:436)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$load$fn__5066.invoke(core.clj:5640)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$load.doInvoke(core.clj:5640)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.RestFn.invoke(RestFn.java:408)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$load_one.invoke(core.clj:5446)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$load_lib$fn__5015.invoke(core.clj:5485)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$load_lib.doInvoke(core.clj:5485)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.RestFn.applyTo(RestFn.java:142)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$apply.invoke(core.clj:626)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$load_libs.doInvoke(core.clj:5524)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.RestFn.applyTo(RestFn.java:137)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$apply.invoke(core.clj:628)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$use.doInvoke(core.clj:5609)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.RestFn.invoke(RestFn.java:408)
12-01 00:57:04.267: E/AndroidRuntime(472): at neko.init$start_repl.doInvoke(init.clj:52)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.RestFn.applyTo(RestFn.java:137)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.core$apply.invoke(core.clj:628)
12-01 00:57:04.267: E/AndroidRuntime(472): at neko.init$init.doInvoke(init.clj:99)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.RestFn.invoke(RestFn.java:410)
12-01 00:57:04.267: E/AndroidRuntime(472): at com.example.myproject.application$app_on_create.invoke(application.clj:96)
12-01 00:57:04.267: E/AndroidRuntime(472): at clojure.lang.Var.invoke(Var.java:379)
12-01 00:57:04.267: E/AndroidRuntime(472): at com.example.myproject.MainApplication$1.run(MainApplication.java:89)
12-01 00:57:04.267: E/AndroidRuntime(472): at java.lang.Thread.run(Thread.java:841)
Neko tries to start nrepl-server and failed. During the build, seems debug configuration would be mixed.
Building project dependency /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib ...
------------------------
Build type: debug, dynamic compilation: enabled, remote REPL: enabled.
------------------------
Building dependency complete.
------------------------
However, next root project seems builded as release.
Compiling 5 source files to /home/yuta/git/myproject/target/release/classes
Applying task compile to nil
All namespaces already AOT compiled.
Running javac with [-target 1.6 -source 1.6 -Xlint:-options @/tmp/.leiningen-cmdline3803311697534617080.tmp]
Compiling Clojure files...
Project classpath: (/opt/android-sdk/tools/support/annotations.jar /opt/android-sdk/platforms/android-15/android.jar /home/yuta/git/myproject/test /home/yuta/git/myproject/src/clojure /home/yuta/git/myproject/resources /home/yuta/git/myproject/target/release/classes /home/yuta/.m2/repository/neko/neko/3.0.2/neko-3.0.2.jar /home/yuta/.m2/repository/clj-time/clj-time/0.6.0/clj-time-0.6.0.jar /home/yuta/.m2/repository/joda-time/joda-time/2.2/joda-time-2.2.jar /home/yuta/.m2/repository/org/clojure-android/clojure/1.6.0-RC1/clojure-1.6.0-RC1.jar /home/yuta/.m2/repository/org/clojure/tools.nrepl/0.2.6/tools.nrepl-0.2.6.jar /home/yuta/.m2/repository/clojure-complete/clojure-complete/0.2.3/clojure-complete-0.2.3.jar /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/target/classes)
Build type: release, dynamic compilation: disabled, remote REPL: disabled.
It's like a confusing problem.
You need completely build-log-file? Or any I need to do?
If you want to check building project yourself, please check my test repo.
Finally, I succeeded executing release-builded app with Admob. Now, I'm creating summarised description. At the latest , and will be able to post on the day after tomorrow .
Great news. I'm sorry I didn't respond. The problem is probably caused by the fact that current profile is not propagated to dependency projects, and it is hard to do that — we can't be sure that the dependency project has :release
profile too. Anyway, I'll be happy to hear your description!
This post explains how to use Google Play Service library. Following steps, you can use Admob, GoogleAnalytics, and others. Of course, also can write layout xml file that contains AdView(if you want).
At first, when you already have projects created by older version of lein-droid
, you have to check and fix some configulation.
project.clj
:
:profiles {...}
elements contains {:default [:dev]}
? :profiles {:default [:dev] ;; <- need, on newer version
...}
:dev|:release
's value is vector? and contains keyword :android-common
? :dev
[:android-common :android-user ;; <- notice, the value is vector, and contains :android-common
{:dependencies [[org.clojure/tools.nrepl "0.2.3"]]
:target-path "target/debug"
:android {:aot :all-with-unused
:rename-manifest-package "sample.lein.droid.admob.debug"
:manifest-options {:app-name "sample-lein-droid-admob - debug"}}}]
:release [{:android ...}]
's value contains :build-type :release
? :release
[:android-common
{:target-path "target/release"
:android
{:ignore-log-priority [:debug :verbose]
:aot :all
:build-type :release}}]} ;; <- need, on newer version
${HOME}/.lein/profiles.clj
:
:android-common
already exists and contains :android {:sdk-path "..."}
?;; My sample
{:user {:plugins [[lein-pprint "1.1.1"]
[lein-kibit "0.0.8"]
[lein-droid "0.3.0-beta4"]]}
:android-user {:plugins [[lein-pprint "1.1.1"]
[lein-kibit "0.0.8"]]}
:android-common {:android {:sdk-path "/opt/android-sdk" ;; <- need, on newer version
:keypass "android"
:storepass "android"}}}
One way to recreate project.clj
: copy old file, generate using lein droid init
, and merge present one manually.
See also: issue #111, #114 .
:android {...
:project-dependencies ["/opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib"]
:external-classes-paths ["/opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar"]
...
project.clj
has these elements, no need to fix.Put GgPS's project.clj
into your GgPS directory.
ex) /opt/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/
(defproject google-play-services_lib/google-play-services_lib "6.1.71-000"
:description "FIXME: Android library description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:min-lein-version "2.0.0"
:source-paths ["src/clojure" "src"]
:java-source-paths ["src/java" "gen"]
:javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]
:java-only true
:profiles {:default [:release]
:release [:android-common]}
:android {:target-version "9"
:library true})
How to create it manually:
lein droid init
.:dependencies
,:java-only true
,:profiles {...}
section.No need clojure and neko for building GgPS, so remove :dependencies
and add :java-only true
.
:profiles
section is a bit complex.
:default [:release]
element needs for lein-droid
, to force using :release
configulation.
If it's not there, lein-droid
can't find :sdk-path
in spite of writing it on ${HOME}/.lein/profiles.clj: :android-common
.
Next key, :release
, need to write value as vector, and add keyword :android-common
for same reason.
There are no need additional elements like :android {:build-type :release}
.
If you don't keep these points, build process makes GGpS that contains clojure and neko with debug.
When debug configuration mixed, it makes you irritated reliably.
In such cases, you must execute lein clean
in GgPS lib's directory.
Unfortunatelly, executing lein clean
in your root project, doesn't target to dependencies.
It's good idea to add cleaning-deps task on your build process, like as a script.
Execute:
lein droid doall
for debuglein with-profile droid doall
for releaseOnce again: Cleaning up dependencies project is strongly recommended.
I found some (maybe) unexpected effects occuerred in lein-droid/src/leiningen/droid/build.clj:161
.
(defn build
"Metatask. Builds dependencies, compiles and creates DEX (if not a library)."
[{{:keys [library]} :android :as project}]
(if library
(doto project
build-project-dependencies code-gen compile crunch-resources)
(doto project
build-project-dependencies code-gen compile create-dex)))
If symbol project
has :project-dependencies
and dependencies contains clojure project, sometimes value in project
changes between processing fn build-project-dependencies
and fn code-gen
.
Hmm...symbol project
is mutable? I don't have much experience at clojure, so I can't understand what was happened.
Thanks!
This is very nice and complete description, Yuta! I can see you solved the profile problem in a dependency project by making a single release profile and removing Clojure and Neko dependencies (which are totally unnecessary there, I agree). That is a good solution. Anyway I still have to fix the profile propagation problem, I hope to get to it some time soon.
Thanks for persistence!
Hi Alex! Many thanks for your comment! I'm glad to discuss with you, I was worried that my poor english makes you frustrated.
I use lein-droid
from 0.1.0(slideshare, sorry japanese) and paused developping by some reason. Long time passed, now, this project has many update, so, until I get used to, took a lot of time.
However, it's all right now.
I feel the project is going to more good one. I'm looking forward to meeting next version!
P.S. Create gisted description. Please copy it if you want.
You shouldn't worry about the language, Yuta, I understand you very well. In fact it is very exciting to know that there is interest for Clojure-Android in different countries, even more so in Japan.
As for your detailed guide, I will try to fix as much as I can on my side, and then intergrate your guide into the tutorial (with attribution to you, of course).
sometimes value in project changes between processing fn build-project-dependencies and fn code-gen.
This could mean that build
is called recursively by the dependency project and thus project
holds a different map. Is it the case?
sometimes value in project changes between processing fn build-project-dependencies and fn code-gen.
This could mean that build is called recursively by the dependency project and thus project holds a different map. Is it the case?
I thought so. But looks different...I don't make it clearly yet.
I'll fix sample admob project and check for details what effects occurred there (with debug-print-implemented lein-droid
, yes, it's traditional way).
It maybe takes several days because my tedious dayjob. :disappointed:
Sorry my mistake. I finally found no problems.
I wonder if lein-droid
shows Build type: debug
when building dependencies.
(in spite of writing :default [:release]
to dependencies project.clj
, and execute lein droid build
)
However, it's no big deal. Build-process works well.
In Japan, amount of clojure-android users looks still less...but hopeful project is growing up(e.g. CLAN, by @ayamada, you know as contributor of lein-droid
).
I hope that lein-droid
is more used in Japan.
It might not make sense to have a "debug" profile for dependencies, if they are just Java projects. I'll probably just remove multiple profiles from library template.
After a long time this issue has been open, I'm finally glad to close it. I don't expect @BartAdv to use Clojure-Android anymore, but still mentioning you. It is very easy to include Google Play Services now.
@sakuraiyuta Thank you for the work you've done on this. Sorry I've never published your guide separately. Still I very much value your contribution, and it helped me to setup the solution we have now.
Documentation mentions
:use-google-api
1, as the way to use additional APIs such as the Google Play Services. However, it just looks insdk/add-ons
directory, whereas Google Play Services are installed in `sdk/extras'.It's possible to refer them via
:external-classes-paths
, but shouldn't there some more easily-configurable way? Should it be hardcoded in the same way the add-ons are searched? (Not sure about this, as (don't know really why), SDK documentation mentions that one should reference local copy instead of the libs installed under sdk directory 2)