3 votes

Android - Utilisation du pipe entre les applications natives et java

Je développe sur SGS2 api v.16

J'ai deux applications : native et Java

Depuis l'application native, j'ouvre un tube Unix avec la fonction mkfifo() et j'y écris une chaîne.

Et dans l'application Java, j'essaie de lire la chaîne de caractères, mais l'application se bloque et je ne peux pas je ne sais pas pourquoi, aucune indication dans le logcat pour savoir pourquoi elle s'est bloquée.

Les deux applications ont Android:sharedUserId="my.Id" dans le manifeste, et le partage a bien fonctionné.

Dans le logcat, je peux voir le log "opening input stream", mais aucun log après cela . Existe-t-il une méthode recommandée pour lire à partir d'un fichier pipe en Java ? NOTE : si j'ouvre un fichier normal avec open(...) au lieu d'utiliser mkfifo(...) je réussis à lire le fichier, le problème ne se pose que lorsque j'ouvre un fichier pipe avec mkfifo()

Voici la fonction exécutée depuis l'application native :

jint Java_com_example_ndkfoo_NdkFooActivity_writeToPipe(JNIEnv* env, jobject javaThis) {
   const char* PATH = "/data/data/com.example.ndkfoo/v_pipe8";
   char* line = "Hello Pipe!";
   int pipe;
   errno = 0;

   // open a named pipe
   mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
   pipe = mkfifo(PATH, mode);
   if(errno != 0) {
        __android_log_write(ANDROID_LOG_ERROR, "NDK_FOO_TAG", strerror(errno));
        return errno;
    }
    __android_log_write(ANDROID_LOG_DEBUG, "NDK_FOO_TAG", "file opened successfully");

   // actually write out the data and close the pipe
   int err = write(pipe, line, strlen(line));

    // close the pipe
   close(pipe);
   return err;

}

Et voici la java qui essaie de lire depuis le tuyau

package com.example.secondparty;

import java.io.FileDescriptor;
import java.io.FileInputStream;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {
     private static final String TAG = MainActivity.class.getSimpleName();
     //public final static String PATH2 = "/sdcard/fifo9001";
     public final static String PATH = "/data/data/com.example.ndkfoo/v_pipe8";

     @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        readFromPipe();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    private void readFromPipe() {
        Log.i(TAG, "Attempt started");
        FileInputStream fis;
        String message = "";
        byte buffer[] = new byte[256];

        try {
            Log.i(TAG, "openning input stream");
            fis = new FileInputStream(PATH);
            Log.i(TAG, "input stream opened");
            FileDescriptor fd =  fis.getFD();
            int len = 0;
            do {
                len = fis.read(buffer);
                if(len > 0) {
                    String newmessage = new String(buffer,0, len, "US-ASCII");
                    message += newmessage;
                }
            } while (len == buffer.length);
            Log.i(TAG, "message: "+message);
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

1voto

Bush Points 593

Utilisez BufferedReader au lieu de `FileInputStream

0voto

Jonathan Points 399

Ici une réflexion très utile sur le cas, avec quelques exemples et explications. http://www.jonathanbeard.io/tutorials/CtoJava

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X