Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one integrate stockfish into an Android App?

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!

like image 549
yarrichar Avatar asked Apr 23 '17 02:04

yarrichar


People also ask

Can I use stockfish in my app?

Run AnywhereYou can use Stockfish on your computer or on your iOS or Android device.

How do you use stockfish on chess app?

You can access Stockfish on Chess.com by going to Chess.com/analysis. Another easy-to-use method of analyzing your games on Chess.com with Stockfish is to select "Analyze" after you complete a game in Live Chess. After you complete a live game on Chess.com, you can select "Analyze" and review your game with Stockfish.

How do you get stockfish 14?

As usual, downloads will be freely available at stockfishchess.org/download. The engine is now significantly stronger than just a few months ago, and wins four times more game pairs than it loses against the previous release version.


2 Answers

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.

like image 144
wp78de Avatar answered Oct 17 '22 04:10

wp78de


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) {
        
    }



like image 42
Develocode 777 Avatar answered Oct 17 '22 04:10

Develocode 777