Как вызвать Clojure на Android?
TL;DR: я не могу вызвать методы Clojure в Android; Я получаю ошибку, и я не уверен, почему.
Я создаю приложение для Android для школьного проекта. Я изучил Clojure, и я хотел бы использовать его для части моего приложения. (Я не собираюсь писать все это в Clojure - только несколько библиотек.)
Я был в состоянии собрать программу Clojure в .jar
и вызывать его из Java, работающей на моем ноутбуке, но я не смог вызвать даже встроенные функции в приложении для Android! Я предполагаю, что мне не хватает библиотеки или чего-то еще, но я здесь в море.
Я сделал следующее, чтобы проверить это:
MainActivity.java
:
package org.wiersdorf.ashton.clojureinterop;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import clojure.java.api.Clojure;
import clojure.lang.IFn;
public class MainActivity extends AppCompatActivity {
private Button BoomButton;
private TextView myText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BoomButton = (Button) findViewById(R.id.my_button);
myText = (TextView) findViewById(R.id.my_text);
BoomButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
IFn plus = Clojure.var("clojure.core", "+");
String foo = plus.invoke(1, 2).toString();
myText.setText("Text: " + foo);
}
});
}
}
activity_main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/my_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/my_text" />
</android.support.constraint.ConstraintLayout>
Когда я нажимаю на кнопку, которая появляется, я получаю эту ошибку:
2018-11-17 23:05:01.313 16202-16202/org.wiersdorf.ashton.clojureinterop E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.wiersdorf.ashton.clojureinterop, PID: 16202
java.lang.ExceptionInInitializerError
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:97)
at clojure.core$fn__8373.invokeStatic(core.clj:7032)
at clojure.core$fn__8373.invoke(core.clj:7027)
at clojure.core__init.load(Unknown Source:7027)
at clojure.core__init.<clinit>(Unknown Source:94)
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
at clojure.lang.RT.classForName(RT.java:2205)
at clojure.lang.RT.classForName(RT.java:2214)
at clojure.lang.RT.loadClassForName(RT.java:2233)
at clojure.lang.RT.load(RT.java:451)
at clojure.lang.RT.load(RT.java:426)
at clojure.lang.RT.doInit(RT.java:469)
at clojure.lang.RT.<clinit>(RT.java:336)
at clojure.lang.Namespace.<init>(Namespace.java:34)
at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
at clojure.lang.Var.intern(Var.java:151)
at clojure.java.api.Clojure.var(Clojure.java:82)
at clojure.java.api.Clojure.<clinit>(Clojure.java:96)
at clojure.java.api.Clojure.var(Clojure.java:82)
at org.wiersdorf.ashton.clojureinterop.MainActivity$1.onClick(MainActivity.java:28)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NoSuchMethodException: canAccess [class java.lang.Object]
at java.lang.invoke.MethodHandles$Lookup.findVirtual(MethodHandles.java:906)
at clojure.lang.Reflector.<clinit>(Reflector.java:38)
Есть идеи? Заранее спасибо.:)
1 ответ
Метод canAccess
был добавлен в Java 9 (см. здесь).
Судя по этой трассировке стека, которая показывает исключение NoSuchMethodException для canAccess
, вы используете jar Clojure, который был скомпилирован с Java 9 или выше, а ваша система Android использует более раннюю JRE.
Если вы можете либо обновить JRE на Android, либо перейти на совместимую версию Clojure, это следует исправить.