16

I'm trying to work out how to integrate stockfish (or any UCI compatible engine) into my Android application.

I've downloaded the stockfish Android zip from here: Download Stockfish Engine.

Under the Android directory of the zip there are two files:

  • stockfish-8-arm64-v8a
  • stockfish-8-armeabi-v7a

I have two questions:

  1. Do I just need to include these two files into my app (and if so where do I put them)? I'm hoping these are pre-built binaries so I don't need to worry about compiling myself.
  2. How do I call into these files from my android Java code?

Thanks!

Ken Graham
  • 121
  • 1
  • 1
  • 6
yarrichar
  • 423
  • 5
  • 17

2 Answers2

10

Stockfish is written in C++, to call it from a regular Android app written in Java, you need to

  1. rely on JNI (Java Native Interface, see jni-sample) to do the trick.
  2. After you have learned how to compile Stockfish with JNI, you can interact with the engine via UCI protocol: Here are the UCI Specification.

  3. Then you can call specific methods (e.g. to evaluate a position, or to suggest the best move). It all starts with sending the engine isready. If you get an answer, you are on the right track.

It would be far easier to modify an existing project like Droidfish instead of starting from scratch.

wp78de
  • 18,207
  • 7
  • 43
  • 71
5

After many days of searching the internet i have found a solution:

  • download source code from https://stockfishchess.org/download/, doesn't matter the platform
  • create a Native C++ project in android studio
  • you can delete the native-lib.cpp file in the cpp folder (and the references in code)
  • extract the content of the downloaded file, go to src folder, copy all the files into the cpp folder of the android project
  • in the CMakeLists.txt(cpp folder) add :
   add_executable(
            stockfish
    
            benchmark.cpp   evaluate.h ...(and the rest of the copied files)
    )
  • in the build.gradle(app) in externalNativeBuild->cmake add targets "stockfish" like so:
externalNativeBuild {
            cmake {
                targets "stockfish"
                cppFlags ""
            }
        }

  • build APK
  • in the folder /app/.cxx/cmake/debug have been generated the folders that contain executables
  • create a new android project without c++ support
  • in the new project in the libs folder copy the folders mentioned above (keep the names), and in each folder delete everything but the stockfish file.
  • rename each stockfish file in each folder like so lib_stockfish.so, now the folders should look like this:
...
-libs
     -arm64-v8a
               -lib_stockfish.so
     -armeabi-v7a
               -lib_stockfish.so
and so on...
...
  • in the build.gradle(app) at android add:
sourceSets {
        main {

            jniLibs.srcDirs = ['libs']
        }
    }
  • in the build.gradle(app) at dependencies add:
implementation fileTree(dir: "libs", include: ["*.jar", "*.so"])
  • in the manifest file in the application tag add:
android:extractNativeLibs="true"
  • now it's just the code in java:

String path = getApplicationContext().getApplicationInfo().nativeLibraryDir+"/lib_stockfish.so";


File file = new File(path);

try {
    process = Runtime.getRuntime().exec(file.getPath());
} catch (IOException e) {
    e.printStackTrace();
}



Thread outThread =  new Thread(new Runnable() {
    @Override
    public void run() {

        Process processOut = process;
        if(processOut == null){
            return;
        }


           BufferedReader out = new BufferedReader(new InputStreamReader(processOut.getInputStream()));

            String data;
            try{


                   while( (data = out.readLine()) != null ){

                    //do something with data
                   }


                } catch(IOException e){
                 
               }

            }
        });

        outThread.start();


///to give commands

String command = "uci";//or other command

command += "\n";

try {
        Process ep = process;

        if (ep != null) {
            ep.getOutputStream().write(command.getBytes());
            ep.getOutputStream().flush();
        }
    } catch (IOException e) {
        
    }



Develocode 777
  • 1,125
  • 9
  • 14
  • hi, thanks for the great explanation, I had been looking for this for the last few days, I followed your instructions but unfortunately, when I ran the code I got the following error `E/error: java.io.IOException: Cannot run program "/data/app/com.example.testc-hUWO86ZpvRLc1on2Z0uyig==/lib/x86/lib_stockfish.so": error=2, No such file or directory`, the error caused by line `process = Runtime.getRuntime().exec(file.getPath());` and even after hours of debugging, I couldn't find the solution, could you pls help me with this, – nikhil123 Jul 29 '20 at 13:45
  • Do you have in the libs folder a folder named x86 containing lib_stockfish.so? – Develocode 777 Jul 30 '20 at 15:14
  • Hi, yes i have a lib_stockfish.so file in libs/x86 folder which I copied from another project and renamed according to your instructions... did it work for you?, I wasted another day trying to find the solution, but no luck , finally I gave up :( – – nikhil123 Jul 30 '20 at 16:10
  • for me yes it works, i am developing a chess game, did you put `jniLibs.srcDirs = ['libs']` in the app gradle like this: `android{...sourceSets { main { jniLibs.srcDirs = ['libs'] }}}`? – Develocode 777 Jul 30 '20 at 16:51
  • Hi, yes I did, I followed your instructions carefully, I uploaded the project to Github https://github.com/nikhilnagpal123/testc, you can see the app Gradle file here https://github.com/nikhilnagpal123/testc/blob/master/app/build.gradle could you pls take a look on that? – – nikhil123 Jul 31 '20 at 05:46
  • you have `implementation fileTree` twice in your gradle, keep only `implementation fileTree(dir: "libs", include: ["*.jar", "*.so"])`, and also you don't need C++ support for this, if it still does't work try making a project without C++ – Develocode 777 Jul 31 '20 at 06:37
  • Hi, Thanks for responding, I just tried that code with a new project without c++ support and removed that extra `implementation fileTree` line but it still gives me the same exception. – nikhil123 Jul 31 '20 at 06:45
  • and also in your MainActivity the name is incomplete `String path = getApplicationContext().getApplicationInfo().nativeLibraryDir+"/_stockfish.so";`, it should be `String path = getApplicationContext().getApplicationInfo().nativeLibraryDir+"/lib_stockfish.so";` – Develocode 777 Jul 31 '20 at 06:46
  • hi, yes I tried `getApplicationContext().getApplicationInfo().nativeLibraryDir+"/lib_stockfish.so";` as well but that didn't work either – nikhil123 Jul 31 '20 at 06:48
  • 1
    it seems i missed something in the original answer, you need to add in your manifest file in the application tag `android:extractNativeLibs="true"`, and also in the MainActivity you should call `outThread.start();` before giving any command to the engine – Develocode 777 Jul 31 '20 at 07:11
  • Finally!... the exception has gone after adding `android:extractNativeLibs="true`, to the manifest file, I can't believe i wasted two days for such a small thing, thank you so much for your help!!! :) – nikhil123 Jul 31 '20 at 07:23
  • Is there a reason why you copy the .so files manually? Can't this be done at compile time? – Christopher Masser Sep 29 '20 at 14:43
  • All that i can tell is that i have tried just about everything and this was the only way it worked. – Develocode 777 Oct 01 '20 at 11:20