clojure-android / lein-droid

A Leiningen plugin for building Clojure/Android projects
Eclipse Public License 1.0
645 stars 56 forks source link

Having trouble with using the REPL to execute code on my device #52

Closed krisc closed 11 years ago

krisc commented 11 years ago

I am using the code generated by following the Tutorial. The only change I made is change the target sdk to 17. When I reach the lein droid doall step, the app opens on my device, then I connect to the port through nREPL in emacs. I then enter the command (in-ns 'org.stuff.clojuroid.main). I start evaluating the forms in the source code to see that the REPL works:

(ns org.stuff.clojuroid.main
  (:use [neko.activity :only [defactivity set-content-view!]]
        [neko.threading :only [on-ui]]
        [neko.ui :only [make-ui]]
        [neko.application :only [defapplication]]))

(defapplication org.stuff.clojuroid.Application)

(defactivity org.stuff.clojuroid.MyActivity
  :def a
  :on-create
  (fn [this bundle]
    (on-ui
     (set-content-view! a
      (make-ui [:linear-layout {}
                [:text-view {:text "Hello from Clojure!"}]])))))

The first two forms return nil. When I evaluate the defactivity form, I get this error:

clojure.lang.Compiler$CompilerException: java.lang.NoClassDefFoundError: android/os/UserHandle, compiling:(NO_SOURCE_PATH:1:1)
 at clojure.lang.Compiler.analyzeSeq (Compiler.java:6567)
    clojure.lang.Compiler.analyze (Compiler.java:6361)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6548)
    clojure.lang.Compiler.analyze (Compiler.java:6361)
    clojure.lang.Compiler.analyze (Compiler.java:6322)
    clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:5708)
    clojure.lang.Compiler$FnMethod.parse (Compiler.java:5139)
    clojure.lang.Compiler$FnExpr.parse (Compiler.java:3751)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6558)
    clojure.lang.Compiler.analyze (Compiler.java:6361)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6548)
    clojure.lang.Compiler.analyze (Compiler.java:6361)
    clojure.lang.Compiler.access$100 (Compiler.java:37)
    clojure.lang.Compiler$DefExpr$Parser.parse (Compiler.java:529)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6560)
    clojure.lang.Compiler.analyze (Compiler.java:6361)
    clojure.lang.Compiler.analyze (Compiler.java:6322)
    clojure.lang.Compiler.eval (Compiler.java:6623)
    clojure.lang.Compiler.eval (Compiler.java:6608)
    clojure.lang.Compiler.eval (Compiler.java:6582)
    clojure.core$eval.invoke (core.clj:2848)
    clojure.main$repl$read_eval_print__6588$fn__6591.invoke (main.clj:264)
    clojure.main$repl$read_eval_print__6588.invoke (main.clj:264)
    clojure.main$repl$fn__6597.invoke (main.clj:282)
    clojure.main$repl.doInvoke (main.clj:281)
    clojure.lang.RestFn.invoke (RestFn.java:1096)
    clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__228.invoke (interruptible_eval.clj:51)
    clojure.lang.AFn.applyToHelper (AFn.java:159)
    clojure.lang.AFn.applyTo (AFn.java:151)
    clojure.core$apply.invoke (core.clj:617)
    clojure.core$with_bindings_STAR_.doInvoke (core.clj:1788)
    clojure.lang.RestFn.invoke (RestFn.java:425)
    clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:36)
    clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__265$fn__268.invoke (interruptible_eval.clj:166)
    clojure.core$comp$fn__4154.invoke (core.clj:2330)
    clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__258.invoke (interruptible_eval.clj:130)
    clojure.lang.AFn.run (AFn.java:24)
    java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1076)
    java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:569)
    java.lang.Thread.run (Thread.java:856)

I am not sure what the error means, but my guess is that my environment is not set up correctly for dynamic compilation.

I am using: clojure-android 1.5.1-SNAPSHOT neko 3.0.0-SNAPSHOT lein 2.3.1 java 1.6.0_45

alexander-yakushev commented 11 years ago

Hello Kris,

You've caught me off guard:). I'm actually update 3.0.0-SNAPSHOT quite often, and few days ago I've introduced some breaking changes. I know that I shouldn't do that. You can try working with 3.0.0-beta1 (version before breaking changes), or you could participate in a beta-test for new Splash window functionality with 3.0.0-beta3. For the latter please also use lein-droid 0.2.0-beta1. Just recreate the project for the latter case with lein droid new (or compare what has changed with sample project in lein-droid repository). Please write back if the problem persists.

krisc commented 11 years ago

Is there some way to check which version of lein-droid I am using? This is what my ~/.lein/profiles.clj looks like:

{:user {:plugins [ [lein-droid "0.2.0-beta1"] ]
          :android {:sdk-path "/home/kris/adt-bundle-linux-x86_64-20130522/sdk/"}}}

When I run DEBUG=1 lein droid doall it gives me no indication that lein-droid 0.2.0-beta1 is being downloaded.

In any case I am now using neko 3.0.0-beta3 and assuming that I am using lein-droid 0.2.0-beta1 I now have a different problem. When launching the APK, the terminal shows no errors:

Launching APK...
/home/kris/adt-bundle-linux-x86_64-20130522/sdk/platform-tools/adb -s TA30000IVO shell am start -n org.stuff.clojuroid/.MyActivity
Starting: Intent { cmp=org.stuff.clojuroid/.MyActivity }
Binding device port 9999 to local port 9999 ...
/home/kris/adt-bundle-linux-x86_64-20130522/sdk/platform-tools/adb -s TA30000IVO forward tcp:9999 tcp:9999

But on my device it says:

Unfortunately,
ClojureMeetsAndroid has
stopped.
alexander-yakushev commented 11 years ago

Actually, if a line in profiles.clj states this version, then you can be sure it is used.

Have you created a new project with newest lein-droid? Also, you can execute adb logcat from your terminal (may need to specify full path to adb, which is <sdk-path>/platform-tools/adb) and then launch the application to see what is the exact reason for crashing. Write it here and we'll continue the investigation.

krisc commented 11 years ago

I created a new project with the newest lein-droid. Now it is showing the exact same error as clojure-android/lein-droid#53.

alexander-yakushev commented 11 years ago

Is there anything in adb logcat?

krisc commented 11 years ago

just like in clojure-android/lein-droid#53, adb logcat stops when installing. Here's some of the last lines of the output:

08-22 12:19:36.496   896   896 I SBar.NetworkController: onDataActivity: direction=0
08-22 12:19:36.506   896   896 I SBar.NetworkController: refreshSignalCluster: mobile: mHasMobileDataFeature=true DataTypeShown=zz_moto_stat_sys_data_fully_connected_4g_lte_waves Activity=zz_moto_stat_sys_data_fully_connected_waves_none Accessibility="4 G L T E"
08-22 12:19:38.559   728   728 D PowerManagerService: acquireWakeLock flags=0x1 tag=RILJ
08-22 12:19:38.559   728   994 D PowerManagerService: releaseWakeLock flags=0x1 tag=RILJ
08-22 12:19:38.569  1077  1077 D ModemStatsService: onSignalStrengthsChanged
08-22 12:19:38.569  1077  1077 D ModemStatsService: LTE, mRssi=-109
08-22 12:19:45.386  1077  1077 D ModemStatsService: onDataActivity
08-22 12:19:45.386  1077  1077 D ModemStatsService: direction is 4
08-22 12:19:45.386   896   896 I SBar.NetworkController: onDataActivity: direction=4
krisc commented 11 years ago

I was going to alternatively try neko 3.0.0-beta1 but then I noticed it's not in https://clojars.org/repo/neko/neko/

alexander-yakushev commented 11 years ago

My bad, I forgot to push it. Please try with that one.

Also I updated lein-droid to 0.2.0-beta2 and neko to 3.0.0-beta5 moving the splash from one part to another. I don't know if things I changed are related to the problem you are having, but you can try that as well.

Btw, have you maybe tried installing app on the emulator? Does that work?

krisc commented 11 years ago

same error using lein-droid 0.2.0-beta2 and neko 3.0.0-beta5. I will try on an emulator in a bit.

alexander-yakushev commented 11 years ago

OK, let's try to do it from the beginning.

If with 0.2.0-beta2 you create a new project using lein droid new and then execute lein droid doall in it, does it work?

krisc commented 11 years ago

Yes, that was what I did. Same error. And just to clarify, my original setup isn't even installing. But I do not know the state of the lein-droid, neko, and clojure-android SNAPSHOTs at that time.

It does not install on an emulator either. Here are the last few lines from adb logcat after trying to install:

I/dalvikvm-heap(  547): Grow heap (frag case) to 13.414MB for 3785616-byte allocation
D/dalvikvm(  547): GC_FOR_ALLOC freed <1K, 13% free 13608K/15492K, paused 176ms, total 176ms
D/dalvikvm(  547): GC_CONCURRENT freed 4K, 13% free 13604K/15492K, paused 56ms+55ms, total 429ms
I/InputDispatcher(  285): Window 'Window{414000c8 u0 com.android.launcher/com.android.launcher2.Launcher}' spent 2011.4ms processing the last input event: MotionEvent(action=1, deviceId=0, source=0x00001002, displayId=0)
I/Choreographer(  547): Skipped 32 frames!  The application may be doing too much work on its main thread.
D/dalvikvm(  547): GC_FOR_ALLOC freed 3702K, 16% free 9908K/11744K, paused 171ms, total 178ms
I/dalvikvm-heap(  547): Grow heap (frag case) to 13.410MB for 3785616-byte allocation
D/dalvikvm(  547): GC_CONCURRENT freed <1K, 12% free 13605K/15444K, paused 27ms+25ms, total 194ms
D/dalvikvm(  547): WAIT_FOR_CONCURRENT_GC blocked 174ms
I/Choreographer(  547): Skipped 125 frames!  The application may be doing too much work on its main thread.
I/Choreographer(  547): Skipped 90 frames!  The application may be doing too much work on its main thread.

And there is no crash or alert on the emulator. adb logcat closes. And no error from lein droid install -e; it just stop after Installing APK...

krisc commented 11 years ago

Silly me! I forgot to run lein droid run after install. It gives me:

Unfortunately,
ClojureMeetsAndroid has
stopped.

Same problem on emulator as on my device.

alexander-yakushev commented 11 years ago

What is adb logcat output when you do lein droid run? There must be something.

krisc commented 11 years ago

Sorry for the late response, but I am away from home until Wednesday and I left my laptop charger at home... so I won't be able to try this until then. Thanks for all your help so far. I feel like you're on to something great here!

alexander-yakushev commented 11 years ago

No problem Kris, I'll be waiting for your feedback.

krisc commented 11 years ago

adb logcat just exits without new messages after lein droid run. But here are the last few lines that were already there before Launching APK...:

E/StrictMode( 1511): null
E/StrictMode( 1511): android.app.ServiceConnectionLeaked: Service com.android.exchange.ExchangeService has leaked ServiceConnection com.android.emailcommon.service.ServiceProxy$ProxyConnection@40d08448 that was originally bound here
E/StrictMode( 1511):    at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:969)
E/StrictMode( 1511):    at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:863)
E/StrictMode( 1511):    at android.app.ContextImpl.bindService(ContextImpl.java:1418)
E/StrictMode( 1511):    at android.app.ContextImpl.bindService(ContextImpl.java:1407)
E/StrictMode( 1511):    at android.content.ContextWrapper.bindService(ContextWrapper.java:473)
E/StrictMode( 1511):    at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:157)
E/StrictMode( 1511):    at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:145)
E/StrictMode( 1511):    at com.android.emailcommon.service.AccountServiceProxy.getDeviceId(AccountServiceProxy.java:116)
E/StrictMode( 1511):    at com.android.exchange.ExchangeService.getDeviceId(ExchangeService.java:1249)
E/StrictMode( 1511):    at com.android.exchange.ExchangeService$7.run(ExchangeService.java:1856)
E/StrictMode( 1511):    at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:551)
E/StrictMode( 1511):    at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:549)
E/StrictMode( 1511):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
E/StrictMode( 1511):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
E/StrictMode( 1511):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
E/StrictMode( 1511):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
E/StrictMode( 1511):    at java.lang.Thread.run(Thread.java:856)
W/ActivityManager( 1114): Unbind failed: could not find connection for android.os.BinderProxy@40ee9710
alexander-yakushev commented 11 years ago

Can you please push your application you are trying to run to the Github so I can check it and see if it works on my setup?

krisc commented 11 years ago

https://github.com/krisc/clojuroid

alexander-yakushev commented 11 years ago

Have you told me that you recreated the project with lein-droid 0.2.0-beta2? Because your project still has neko 3.0.0-beta1 in the dependencies. Change it to 3.0.0-beta5, then execute lein clean && lein droid doall.

krisc commented 11 years ago

Sorry, my mistake. I already tried neko 3.0.0-beta5 and did not work, so I changed it to neko 3.0.0-beta1, and that didn't work either. I forgot to change it back to beta5 before pushing.

I did indeed recreate the project with lein-droid 0.2.0-beta2. However, I did not do lein clean before lein droid doall until now, and now it works! (why is this so?)

Now, back to the original problem: I evaluated the defactivity form, and now that works too. Great! I will now try on my device again and report back.

krisc commented 11 years ago

On my device, we're back to the problem in clojure-android/lein-droid#53.

alexander-yakushev commented 11 years ago

I'm glad it works now! So is this issue resolved?

Speaking of lein clean, I don't know why, but some old compiled classes probably messed with the whole application. Clean just deletes a target folder.

krisc commented 11 years ago

Yes, thanks again for all your help!

krisc commented 11 years ago

Hmmm, I can execute code in emacs through nREPL without getting errors, but if I change the text of the text view then evaluate the defactivity form, shouldn't the text in the running app change? Nothing is happening.

alexander-yakushev commented 11 years ago

When you redefine toplevel defactivity form, you won't see changes until activity is recreated (for example, if you tilt the device so orientation changes). To see changes immediately, evaluate inside form starting with on-ui.

krisc commented 11 years ago

okay so in the toplevel I have this form:

(on-ui
  (set-content-view!
    (make-ui [:linear-layout {}
             [:text-view {:text "yeah, hello, um"}]])))

When I evaluate this I get:

java.lang.AssertionError: Assert failed: (activity? activity)

When I call (has-*activity*?) it returns false. So it seems that I don't have an activity bound, but isn't that what the defactivity form did?

alexander-yakushev commented 11 years ago

Well, you missed a as first arguments to set-content-view!. It should be:

(on-ui
  (set-content-view! a
    (make-ui [:linear-layout {}
              [:text-view {:text "Wassup"}]])))

I didn't mean you had to copy this form into top level, it is just that if you want to see changes immediately, put your cursor onto previous-to-last closing paren (so that on-ui form becomes highlighted) and press C-x C-e.

krisc commented 11 years ago

I got it to work another way. I took out the :def a line so that the var mainActivity will be accessible outside of the defactivity form. But I like your way more haha. I didn't know you can do that. That will come in handy!