Reputation: 7986
I'm trying to consume a SOAP service in my Android app. I'm trying to follow this guide. When I try to run my app I get an error:
Error: MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)
I'm on Android N (SDK 25 - I can't bump to 26 like the error message indicates) and it's a brand new project just created by Android Studio.
Here's my project build.gradle file which I haven't changed:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
And here's my app build.gradle file:
apply plugin: 'com.android.application'
configurations {
jaxb
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE")
}
}
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
repositories {
mavenCentral()
}
// tag::wsdl[]
task genJaxb {
ext.sourcesDir = "${buildDir}/generatedjava/jaxb"
ext.classesDir = "${buildDir}/classes/jaxb"
ext.schema = "https://lite.realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2017-10-01"
outputs.dir classesDir
doLast() {
project.ant {
taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
classpath: configurations.jaxb.asPath
mkdir(dir: sourcesDir)
mkdir(dir: classesDir)
xjc(destdir: sourcesDir, schema: schema,
package: "hello.wsdl") {
arg(value: "-wsdl")
produces(dir: sourcesDir, includes: "**/*.java")
}
javac(destdir: classesDir, source: 1.8, target: 1.8, debug: true,
debugLevel: "lines,vars,source",
classpath: configurations.jaxb.asPath) {
src(path: sourcesDir)
include(name: "**/*.java")
include(name: "*.java")
}
copy(todir: classesDir) {
fileset(dir: sourcesDir, erroronmissingdir: false) {
exclude(name: "**/*.java")
}
}
}
}
}
// end::wsdl[]
android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.example.magicmirror"
minSdkVersion 25
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
exclude 'META-INF/spring.tooling'
exclude 'META-INF/spring.handlers'
exclude 'META-INF/spring-configuration-metadata.json'
exclude 'META-INF/additional-spring-configuration-metadata.json'
exclude 'META-INF/spring.factories'
exclude 'META-INF/spring.schemas'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation "org.springframework.boot:spring-boot-starter"
implementation "org.springframework.ws:spring-ws-core"
implementation(files(genJaxb.classesDir).builtBy(genJaxb))
jaxb "com.sun.xml.bind:jaxb-xjc:2.1.7"
}
From the logs the exact JAR causing this is org.springframework/spring-core/5.1.8.RELEASE.jar
. Adding the compileOptions
block is mentioned in other answers as a fix but it hasn't fixed this issue. How can I fix this?
Upvotes: 7
Views: 4563
Reputation: 76699
org.springframework/spring-core/5.1.8.RELEASE.jar
won't work with minSdkVersion 25
and it's not even and Android library, but a Java library. It strictly demands minSdkVersion 26
:
MethodHandle.invoke and MethodHandle.invokeExact
are only supported starting with Android O (--min-api 26)
ksoap2-android might indeed be more compatible (the most common) or
wsdl2ksoap2-android with on-device "automatic source code generating from WSDL".
... there are a few others linked; some require POJO generation on Desktop Java.
Upvotes: 0
Reputation: 4335
Did you try ksoap?
https://github.com/simpligility/ksoap2-android
Looks like it should do soap, is alive and works for android.
The ksoap2-android project provides a lightweight and efficient SOAP client library for the Android platform.
Upvotes: 3
Reputation: 1698
I think you just need to use a different library in order to make your SOAP calls. This is what I've used which supports versions of the SDK as far back as 14.
private void GetSomeStuff(String myterm) throws UnsupportedEncodingException {
try {
String strStuff2 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"+
"<soap:Header><wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">"+
"<wsse:UsernameToken><wsse:Username>my username</wsse:Username><wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">my password</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header>"+
"<soap:Body> <GetSomeStuff xmlns=\"https://mycompany.com.MyService\">"+
"<term>" + myterm + "/term></GetSomeStuff></soap:Body></soap:Envelope>";
StringBuilder stringBuilder = new StringBuilder();
HttpPost httppost = new HttpPost("https://mycompany.com/MyService.svc");
StringEntity se;
se = new StringEntity(strStuff2,HTTP.UTF_8);
httppost.setHeader("SOAPAction", "https://mycompany.com.MyService/GetSomeStuff”);
se.setContentType("text/xml");
httppost.setEntity(se);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse theresponse = (HttpResponse) httpclient.execute(httppost);
StatusLine statusLine = theresponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = theresponse.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
String theXML = stringBuilder.toString();
int start = theXML.indexOf("<GetSomeStuffResult>") + 21;
int end = theXML.indexOf("</GetSomeStuffResult>") - 1;
// We didn't get the response we expected
if ((start < 0) || (end < 0) || (start==end)) {
Log.i(“MyApp”,”Empty Response from GetSomeStuffResult");
return;
}
String myData = theXML.substring(start, end);
if (myData() > 0) {
try {
JSONObject jObject = new JSONObject(myData);
String deptDesc = jObject.getString("DepartmentDescription");
String areaCode = jObject.getString("area_code");
String phoneNumber = jObject.getString("phone_nbr");
String title = jObject.getString("title");
String fullPhoneNumber = "";
if (phoneNumber.length() == 7) {
fullPhoneNumber = "(" + areaCode + ") " + phoneNumber.substring(0, 3) + "-" + phoneNumber.substring(3, 7);
} else {
fullPhoneNumber = "(" + areaCode + ") " + phoneNumber;
}
SharedPreferences appPrefs =
getSharedPreferences("appPreferences",MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = appPrefs.edit();
prefsEditor.putString("Title",title);
prefsEditor.putString("DeptDescr",deptDesc);
prefsEditor.putString("PhoneNumber",fullPhoneNumber);
prefsEditor.commit();
}
catch (JSONException e) {
e.printStackTrace();
}
}
} else {
Log.e(“MyApp”, "Failed to GetSomeStuff”);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Upvotes: 0