Italian Utilizzo di ProcessBuilder all'interno di una Java Library

Stolcius Von Stolcenberg

Member
Licensed User
Salve, come avevo già prospettato in un precedente 3D, ho l'insana intenzione di implementare una gui che si interfacci con gli engine scacchistici.

Su consiglio di Marco Rame(QUI) , sto codificando una libreria Java che mi permetta di comunicare con uno dei predetti engine, vale a dire Stockfish for android(stockfish-8-arm64-v8a), scaricabile da questo link https://stockfishchess.org/download/


Al momento, il codice è il seguente:
B4X:
package anywheresoftware.b4a.objects;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.CompoundButton.OnCheckedChangeListener;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Hide;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.keywords.Common.DesignerCustomView;
import anywheresoftware.b4a.keywords.constants.Colors;
import anywheresoftware.b4a.keywords.Common;
import  java.io.*;
//import java.lang.ProcessBuilder;
@ShortName("ChessLib2")
public class ChessLib2 {
    private BA ba;
 
    ProcessBuilder pb;
    Process p=null;
    InputStream in    = null;
    OutputStream out  = null;

     public void setup() {
        Common.Log("inside setup");
        /*
          Engine stockfish 'stockfish-8-arm64-v8a' for android scaricato da https://stockfishchess.org/download/
          e caricano nel progetto B4A
        */
        String fileEngine ="stockfish-8-arm64-v8a";
       
        String filePathString = anywheresoftware.b4a.objects.streams.File.virtualAssetsFolder;
       
        String fileFullPath = filePathString + "/" + fileEngine;
       
        Common.Log("fileFullPath: " + fileFullPath);
       
        //controllo che il file sia visibile da codice Java
        File varTmpDir = new File(fileFullPath);
        boolean exists = varTmpDir.exists();
        Common.Log("file exists:" + exists);
       
        pb = new ProcessBuilder( fileFullPath, "" );
        try {
             p = pb.start();
             Common.Log("Processo OK!");
            } catch (Exception e) {
              Common.Log("Errore:" +  e);
        }
        Common.Log("fine proc setup");
     }
  
      
}

Come potete notare, per comunicare con l'engine stockfish-8-arm64-v8a, caricato su B4A con il File Manager, viene utilizzato il Java ProcessBuilder, che permette di scambiare comandi UCI tramite InputStream/OutputStream.
Il problema, però, è che la func setup() mi va in errore nella riga dove viene istanziato il ProcessBuilder
B4X:
  pb = new ProcessBuilder( fileFullPath, "" );

Il seguente(LOG):

B4X:
** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
inside setup
fileFullPath: /data/user/0/b4a.stolcius.chessgui/files/virtual_assets/stockfish-8-arm64-v8a
file exists:true
Errore:java.io.IOException: Error running exec(). Command: [/data/user/0/b4a.stolcius.chessgui/files/virtual_assets/stockfish-8-arm64-v8a, ] Working Directory: null Environment: [ANDROID_ROOT=/system, ANDROID_BOOTLOGO=1, EXTERNAL_STORAGE=/sdcard, SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/wifi-service.jar, ANDROID_SOCKET_zygote=11, PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin, ANDROID_DATA=/data, ANDROID_ASSETS=/system/app, ASEC_MOUNTPOINT=/mnt/asec, BOOTCLASSPATH=/system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/system/framework/apache-xml.jar:/system/framework/org.apache.http.legacy.boot.jar, ANDROID_PROPERTY_WORKSPACE=9,0, ANDROID_STORAGE=/storage]
fine proc setup
** Activity (main) Resume **

Un aiutino?
Stolcius
 

MarcoRome

Expert
Licensed User
Longtime User
Il file
stockfish-8-arm64-v8a lo hai aggiunto nella cartella "lib" ?
 

Stolcius Von Stolcenberg

Member
Licensed User
Non ho capito ...puoi spiegarti meglio
GUI B4A -> Files Manager -> Add Files (vedi snapshot allegato)

File.Exists(File.DirAssets,"stockfish-8-arm64-v8a") risponde True
 

Attachments

  • Files_Manager_Snapshot.JPG
    Files_Manager_Snapshot.JPG
    12.7 KB · Views: 278

MarcoRome

Expert
Licensed User
Longtime User
Allora quando crei un wrapper non funziona in questo modo. I files in questione :

upload_2017-3-19_18-2-59.png


Devono essere inseriti all'interno del wrapper che tu crei.

SS-2013-06-04_19.29.16.png


Se vedi nella struttura esiste una cartella libs. Devi copiare gli stessi li.
Ti consiglio di vedere per benino altri esempi di wrapper.
 

Stolcius Von Stolcenberg

Member
Licensed User
Allora quando crei un wrapper non funziona in questo modo. I files in questione :

View attachment 53905

Devono essere inseriti all'interno del wrapper che tu crei.

SS-2013-06-04_19.29.16.png


Se vedi nella struttura esiste una cartella libs. Devi copiare gli stessi li.
Ti consiglio di vedere per benino altri esempi di wrapper.

Grazie, Marco, il problema però è che per me stockfish-8-arm64-v8a è una black box: non è un file .java e, una volta inserito nella cartella libs, non saprei come interfacciarmi con esso.

Pensavo che potesse essere invocato come processo più o meno nello stesso modo che si usa con gli eseguibili .exe, per intenderci...

Ho anche provato a utilizzare il metodo shell della lib Phone :

B4X:
    Dim p As Phone
    Dim sb As StringBuilder
    sb.Initialize
    p.Shell(fileFullPath, Null, sb,Null )

Ricevendo uno squillante errore: "Caused by: java.io.IOException: No such file or directory".

Oltretutto, questi motori sono fatti per essere caricati/scaricati dalle GUI scacchistiche a piacimento e non inchiavardati dentro una library.

Mi ritrovo in una situazione di stallo(chiaramente dovuta in gran parte alla mia inesperienza in questo ambito).


Grazie K per i consigli,
Stolcius
 

MarcoRome

Expert
Licensed User
Longtime User
Allora invece di creare un wrapper prova ad utilizzare JavaObject è davvero molto potente.
Per avere un'idea su come utilizzarlo guarda QUI
 

MarcoRome

Expert
Licensed User
Longtime User
Top