Archived

This forum has been archived. Please start a new discussion on GitHub.

Slice Android Studio

Could you explain how include the slice2java generated classes in Android Studio Project

Thanks for your help.

here is my build.gradle :

buildscript {

repositories {
    google()
    jcenter()

    mavenCentral()
    maven {
        url "https://plugins.gradle.org/m2/"
    }
}
dependencies {
    classpath 'com.android.tools.build:gradle:3.1.1'
    classpath "gradle.plugin.com.zeroc.gradle.ice-builder:slice:1.4.5"


    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

}

apply plugin: 'java'
apply plugin: 'slice'
slice {
java {
srcDir = '.'
}
}
dependencies {
compile 'com.zeroc:ice:3.7.0'
}

allprojects {
repositories {
google()
jcenter()
}
}

Comments

  • xdm
    xdm La Coruña, Spain

    The buildscript part seems correct, but the project setup seems not.

    Not need to apply Java plug-in on Android, the compile dependencies are not longer used in android it is now implementation.

    I just tested with Android Studio 3.1.2, something along this lines should work for your project build.gradle

    apply plugin: 'com.android.application'
    apply plugin: 'com.zeroc.gradle.ice-builder.slice'
    
    slice.output = file("${project.buildDir}/generated/source/ice")
    
    android {
        compileSdkVersion 26
        defaultConfig {
            applicationId "minimal"
            minSdkVersion 25
            targetSdkVersion 26
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
    
    dependencies {
        implementation fileTree(include: ['*.jar'], dir: 'libs')
        implementation 'com.android.support:appcompat-v7:26.1.0'
        implementation 'com.android.support.constraint:constraint-layout:1.1.0'
        implementation 'com.android.support:design:26.1.0'
        implementation 'com.zeroc:ice:3.7.1'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    }
    

    You are at-least missing the slice.output setting and the implementation 'com.zeroc:ice:3.7.1' you should also use the full name to apply the slice plug-in apply plugin: 'com.zeroc.gradle.ice-builder.slice' and do not apply Java plug-in in android projects.

    Cheers,
    José

  • neros
    edited May 2018

    Thanks for reply, I have this errors with this build.gradle

  • xdm
    xdm La Coruña, Spain

    This seems unrelated to the Ice builder, from your log:

    Caused by: org.gradle.api.plugins.UnknownPluginException: Plugin with id 'com.android.application' not found.
    

    Seems like your android project is not correctly setup, I will suggest that you try to start by creating a fresh android project then modify it to include the builder should be simpler.

  • // Top-level build file where you can add configuration options common to all sub-projects/modules.

    buildscript {

    repositories {
        google()
        jcenter()
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.1'
        classpath "gradle.plugin.com.zeroc.gradle.ice-builder:slice:1.4.5"
    
    
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
    

    }

    apply plugin: 'java'
    apply plugin: 'slice'
    slice {
    java {
    srcDir = '.'
    }
    }
    dependencies {
    compile 'com.zeroc:ice:3.7.0'
    }
    allprojects {
    repositories {
    google()
    jcenter()
    }
    }

    Error:Static interface methods are only supported starting with Android N (--min-api 24): void com.zeroc.Ice.Object._iceCheckMode(com.zeroc.Ice.OperationMode, com.zeroc.Ice.OperationMode)
    Error:com.android.builder.dexing.DexArchiveBuilderException: Failed to process /home/user/.gradle/caches/modules-2/files-2.1/com.zeroc/ice/3.7.0/6680e137309ee807f890a15aa39f7dd612477fe8/ice-3.7.0.jar
    Error:com.android.builder.dexing.DexArchiveBuilderException: Error while dexing.
    Error:com.android.tools.r8.CompilationFailedException: Compilation failed to complete
    Error:com.android.tools.r8.utils.AbortException

  • Android Studio can see slice generated package and run emulator, but I have this errors when I lunch the ice client :

    com.zeroc.Ice.SocketException
        error = 0
        at com.zeroc.IceInternal.OutgoingAsync.waitForResponseOrUserEx(OutgoingAsync.java:146)
        at com.zeroc.IceInternal.OutgoingAsync.waitForResponse(OutgoingAsync.java:118)
        at com.zeroc.Ice._ObjectPrxI.ice_isA(_ObjectPrxI.java:36)
        at com.zeroc.Ice.ObjectPrx$$CC._checkedCast$$STATIC$$(Unknown Source:862)
        at com.zeroc.Ice.ObjectPrx$$CC._checkedCast$$STATIC$$(Unknown Source:824)
        at MP3.ClientMetaServeurPrx$$CC.checkedCast$$STATIC$$(Unknown Source:269)
        at m1.tp1.tp1.ClientServeur.<init>(ClientServeur.java:20)
        at m1.tp1.tp1.ListeMorceaux$1.onClick(ListeMorceaux.java:30)
        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.net.SocketException: Permission denied
        at sun.nio.ch.Net.socket0(Native Method)
        at sun.nio.ch.Net.socket(Net.java:420)
        at sun.nio.ch.Net.socket(Net.java:413)
        at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:128)
        at sun.nio.ch.SelectorProviderImpl.openSocketChannel(SelectorProviderImpl.java:60)
        at java.nio.channels.SocketChannel.open(SocketChannel.java:145)
        at com.zeroc.IceInternal.Network.createTcpSocket(Network.java:146)
        at com.zeroc.IceInternal.StreamSocket.<init>(StreamSocket.java:22)
        at com.zeroc.IceInternal.TcpConnector.connect(TcpConnector.java:17)
        at com.zeroc.IceInternal.OutgoingConnectionFactory$ConnectCallback.nextConnector(OutgoingConnectionFactory.java:1087)
        at com.zeroc.IceInternal.OutgoingConnectionFactory$ConnectCallback.access$100(OutgoingConnectionFactory.java:852)
        at com.zeroc.IceInternal.OutgoingConnectionFactory.getConnection(OutgoingConnectionFactory.java:553)
        at com.zeroc.IceInternal.OutgoingConnectionFactory.access$800(OutgoingConnectionFactory.java:15)
        at com.zeroc.IceInternal.OutgoingConnectionFactory$ConnectCallback.getConnection(OutgoingConnectionFactory.java:1032)
        at com.zeroc.IceInternal.OutgoingConnectionFactory$ConnectCallback.connectors(OutgoingConnectionFactory.java:916)
        at com.zeroc.IceInternal.EndpointHostResolver.resolve(EndpointHostResolver.java:52)
        at com.zeroc.IceInternal.ProtocolInstance.resolve(ProtocolInstance.java:109)
        at com.zeroc.IceInternal.IPEndpointI.connectors_async(IPEndpointI.java:114)
        at com.zeroc.IceInternal.OutgoingConnectionFactory$ConnectCallback.nextEndpoint(OutgoingConnectionFactory.java:1014)
        at com.zeroc.IceInternal.OutgoingConnectionFactory$ConnectCallback.getConnectors(OutgoingConnectionFactory.java:1004)
        at com.zeroc.IceInternal.OutgoingConnectionFactory$ConnectCallback.access$000(OutgoingConnectionFactory.java:852)
        at com.zeroc.IceInternal.OutgoingConnectionFactory.create(OutgoingConnectionFactory.java:209)
        at com.zeroc.IceInternal.RoutableReference.createConnection(RoutableReference.java:838)
        at com.zeroc.IceInternal.RoutableReference.getConnectionNoRouterInfo(RoutableReference.java:564)
        at com.zeroc.IceInternal.RoutableReference.getConnection(RoutableReference.java:555)
        at com.zeroc.IceInternal.RequestHandlerFactory$1.call(RequestHandlerFactory.java:66)
        at com.zeroc.IceInternal.RequestHandlerFactory$1.call(RequestHandlerFactory.java:62)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    
  • xdm
    xdm La Coruña, Spain

    The JavaMapping requires Android 7 (API24) and Source Compatibility / Language Compatibility 1.8

    If you need to target an older API you can use the JavaCompat mapping you should use ice-compat-3.7.1.jar instead of ice-3.7.1.jar

    You also need to configure the slice plugin to use the compat mapping by setting

    slice.compat = true
    
  • Thanks, But I have a big problem : I use serialized object to String in order to exchange data between Android Ice Client and Linux Ubuntu Ice Server

    But when the Server try to convert String to object, there is an error : java.io.StreamCorruptedException: invalid stream header: EFBFBDEF

    Code used to serialize :

                 try {
                     ByteArrayOutputStream bo = new ByteArrayOutputStream();
                     ObjectOutputStream so = new ObjectOutputStream(bo);
                     so.writeObject(morceau);
                     so.flush();
    
                     return ((String) bo.toString());
    
                 } catch (Exception e) {
                     System.out.println(e);
                 }
    

    Unserialize :

         try {
    
             byte b[] = morceauSerialize.getBytes(); 
             ByteArrayInputStream bi = new ByteArrayInputStream(b);
             ObjectInputStream si = new ObjectInputStream(bi);
             Morceau morceau = (Morceau) si.readObject();
             morceau.setId((long) this.listeMorceaux.size());
             System.out.println("Titre morceau ajoute " + morceau.getTitre());
    
    
    
    
         } catch (Exception e) {
             System.out.println(e);
         }
    
  • xdm
    xdm La Coruña, Spain

    You should review the serialize demo for the proper way to do that https://github.com/zeroc-ice/ice-demos/tree/master/java/Ice/serialize

  • neros
    edited May 2018

    Thanks.

    In this demo. the java class to serialize is seen as a byte sequence but my java class has attributes and methods.

    Here is my Morceau class :

    import java.io.Serializable;

    public class Morceau implements java.io.Serializable {

    private String titre;
    
    private String interprete;
    
    private String genre;
    
    private String url;
    
    private long id;
    
    
    public Morceau(String titre, String interprete, String genre, String url, long id) {
    
        this.setTitre(titre);
    
        this.setInterprete(interprete);
    
        this.setGenre(genre);
    
        this.setURL(url);
    
        this.setId(id);
    }
    
    public Morceau() {
    
    }
    
    public String getTitre() {
        return titre;
    }
    
    public void setTitre(String titre) {
        this.titre = titre;
    }
    
    public String getInterprete() {
        return interprete;
    }
    
    public void setInterprete(String interprete) {
        this.interprete = interprete;
    }
    
    public String getGenre() {
        return genre;
    }
    
    public void setGenre(String genre) {
        this.genre = genre;
    }
    
    public String getURL() {
        return url;
    }
    
    public void setURL(String cheminFichier) {
        this.url = cheminFichier;
    }
    
    public long getId() {
        return id;
    }
    
    public void setId(long id) {
        this.id = id;
    }
    

    }

  • xdm
    xdm La Coruña, Spain

    The fact that a class has methods it is irrelevant with respect to serialization. I think this demo does exactly what you need send a java.io.Serializable type over the wire using an operation defined in Slice

    If you review the demo all the serialization and deserialization of the Java objects is automatically handle by Ice when you use the appropriate Slice metadata

    On the client side the application pass an instance of the class MyGreeting to the sendGreeting operation, the Ice run-time serialize the Java object using java.io.Serializable interface and send it over the wire as a Slice sequence of bytes.

    On the server side the Ice run-time reads the sequence of bytes, deserialize the object creating an instance of MyGreeting class and pass it as a parameter to the sendGreeting dispatch method.

    The client and server only deal with the Java type MyGreeting and serialization is automatically handle by Ice run-time.

    Your code to serialize the object does not seems correct specially the toString conversion, this is not the serialized data but a description of the ByteArrayOutputStream object.

    Cheers,
    Jose

  • Thanks, my method to add an object to the server "works", but I have an error in Android and I can't find why :

    android.os.NetworkOnMainThreadException
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1450)
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:52)
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
    at sun.nio.ch.IOUtil.write(IOUtil.java:65)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:510)
    at com.zeroc.IceInternal.StreamSocket.write(StreamSocket.java:232)
    at com.zeroc.IceInternal.StreamSocket.write(StreamSocket.java:175)
    at com.zeroc.IceInternal.TcpTransceiver.write(TcpTransceiver.java:57)
    at com.zeroc.Ice.ConnectionI.write(ConnectionI.java:3011)
    at com.zeroc.Ice.ConnectionI.sendMessage(ConnectionI.java:2393)
    at com.zeroc.Ice.ConnectionI.initiateShutdown(ConnectionI.java:2018)
    at com.zeroc.Ice.ConnectionI.setState(ConnectionI.java:1985)
    at com.zeroc.Ice.ConnectionI.setState(ConnectionI.java:1793)
    at com.zeroc.Ice.ConnectionI.destroy(ConnectionI.java:161)
    at com.zeroc.IceInternal.OutgoingConnectionFactory.destroy(OutgoingConnectionFactory.java:68)
    at com.zeroc.IceInternal.Instance.destroy(Instance.java:1418)
    at com.zeroc.Ice.CommunicatorI.close(CommunicatorI.java:18)
    at m1.tp1.Serveur.ClientServeur.ajoutMorceau(ClientServeur.java:34)
    at m1.tp1.Serveur.Ajout.ajouter(Ajout.java:61)
    at m1.tp1.Serveur.Ajout.access$000(Ajout.java:13)
    at m1.tp1.Serveur.Ajout$1.onClick(Ajout.java:44)
    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)

  • xdm
    xdm La Coruña, Spain

    The problem is that android disallow network activity on the MainThread. Only Ice asynchronous APIs must be used from android MainThread.

    In this case Communicator destroy is executed in main thread and it is causing the problem, there is currently no asynchronous API to destroy the communicator so you should ensure this method is from a separate thread and never from MainThread.

  • The application run successible with Android device emulator, but I have an java.lang.NoClassDefFoundError: com.zeroc.IceInternal.Instance error with a connected device (Android 6, API 23)

    Gradle config in attachment

  • xdm
    xdm La Coruña, Spain

    The Java mapping requires Android 7 Api 24, for previous android versions you can use the Java-Compat mapping

    see supported platforms

  • The server side is very complexe, I have to make a lots of changes ?

  • xdm
    xdm La Coruña, Spain

    You have to use java-compat mapping only for the android application, you can keep using java mapping for the server side.

  • I can't see the difference for client

    My current client is some functions like this :

        String[] params = null;
    
        try (com.zeroc.Ice.Communicator communicator = com.zeroc.Ice.Util.initialize(params)) {
    
    
            com.zeroc.Ice.ObjectPrx base = communicator.stringToProxy("clientmetaserveur:default -h " + adresseIP + " -p 10045");
            MP3.ClientMetaServeurPrx printer = MP3.ClientMetaServeurPrx.checkedCast(base);
            if (printer == null) {
                throw new Error("Invalid proxy");
            }
    
            Morceau morceau = new Morceau();
    
            morceau.titre = titre;
    
            printer.deleteMorceau(morceau);
    
        }
    

    Could you help me to find what I have to change ?

  • I have change my gradle with :

    // Top-level build file where you can add configuration options common to all sub-projects/modules.

    buildscript {

    repositories {
        google()
        jcenter()
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'
        classpath "gradle.plugin.com.zeroc.gradle.ice-builder:slice:1.4.5"
    
    
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
    

    }

    apply plugin: 'java'
    apply plugin: 'slice'
    slice {
    java {
    srcDir = '.'
    compat = true
    }
    }
    dependencies {
    compile 'com.zeroc:ice-compat:3.7.0'
    }
    allprojects {
    repositories {
    google()
    jcenter()
    }
    }

    but doesn't works

  • xdm
    xdm La Coruña, Spain

    The generated code for java-compat is different as it doesn't depend on new features that are only available with Java 8 and up, for compat mapping the Ice types are in Ice package and not in com.zeroc.Ice.

    Your sample above will look something like this with java-compat mapping

        String[] params = null;
    
        try (Ice.Communicator communicator = Ice.Util.initialize(params)) {
    
    
            com.zeroc.Ice.ObjectPrx base = communicator.stringToProxy("clientmetaserveur:default -h " + adresseIP + " -p 10045");
            MP3.ClientMetaServeurPrx printer = MP3.ClientMetaServeurPrxHelper.checkedCast(base);
            if (printer == null) {
                throw new Error("Invalid proxy");
            }
    
            Morceau morceau = new Morceau();
    
            morceau.titre = titre;
    
            printer.deleteMorceau(morceau);
    
        }
    

    You should review the java-compat mapping documentation for the details

  • Thnaks, but Android studio doesn't resolve Ice.Communicator

  •    try (Ice.Communicator communicator = Ice.Util.initialize()) {
    
    
            Ice.ObjectPrx base = communicator.stringToProxy("clientmetaserveur:default -h " + adresseIP + " -p 10045");
            MP3.ClientMetaServeurPrx printer = MP3.ClientMetaServeurPrx.checkedCast(base);
            if (printer == null) {
                throw new Error("Invalid proxy");
            }
    
    
    
            listTemp = printer.getListeMorceaux();
    
            printer.dumpReponse();
    
    
        }
    

    java.lang.ClassCastException: Ice.ObjectPrxHelperBase cannot be cast to com.zeroc.Ice.ObjectPrx

  • xdm
    xdm La Coruña, Spain

    Android studio doesn't resolve Ice.Communicator

    Ice.Communicator is part of ice-compat.jar

    java.lang.ClassCastException: Ice.ObjectPrxHelperBase cannot be cast to com.zeroc.Ice.ObjectPrx

    Seems to me you are mixing the code generated with no compat with the compat jars

            MP3.ClientMetaServeurPrx printer = MP3.ClientMetaServeurPrx.checkedCast(base);
    

    With the compat mapping this should be

            MP3.ClientMetaServeurPrx printer = MP3.ClientMetaServeurPrxHelper.checkedCast(base);
    

    For example with the compat mapping the checkedCast operation is provided by the helper class and not by the proxy interface.

    slice {
    java {
    srcDir = '.'
    compat = true
    }
    }
    

    That is probably the cause, compat is a property of the slice plug-in object not part of the java source set, try:

    slice.compat = true
    
    slice {
      java {
        srcDir = '.'
      }
    }