2

I need to grab text questions from C binary and display it in my TextView. Also, I need to grab an answers from input field and pass it to C binary, etc. I read this topic and tried to run it on Android. C binary works in shell, but my app doesn't work (blank screen). I am very new in Java and I need help.

package com.example.helloapp;

import android.app.Activity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Toast;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;
import java.io.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;


public class HelloApp extends Activity
{
    private Button btn;
    private EditText editText;
    private TextView textView;

    private BlockingQueue<String> m_queue;
    private BufferedReader bufIn;
    private InputStream in;
    private InputThread inputThread;
    private PrintWriter printOut;
    private Process p;

    private Handler handler;

    private String input = null;

// show nice popup on error
    private void popup(String msg)
    {
        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
    }

    Thread.UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler()
    {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            e.printStackTrace();
            HelloApp.this.finish();
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textView = (TextView)findViewById(R.id.textView1);
        btn = (Button)findViewById(R.id.button1);

        Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);

// new Thread cannot change our TextView, so we use Handler
        handler = new Handler()
        {
            @Override
            public void handleMessage(Message msg)
            {
                String text = (String) msg.obj;
                textView.setText(text);
            }
        };

        File f = new File(getCacheDir()+"/hello");

        if(!f.exists())
        try {
// unpack our binary...
            InputStream is = getAssets().open("hello");
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();

            FileOutputStream fos = new FileOutputStream(f);
            fos.write(buffer);
            fos.close();

// ... and make it executable
            try {
                Process chmod = Runtime.getRuntime().exec("/system/bin/chmod 777 " +f.getPath());
                chmod.waitFor();
            } catch(IOException e) { popup(e.getMessage()); } catch(InterruptedException e) { popup(e.getMessage()); }

        } catch(IOException e) { popup(e.getMessage()); }

        try {
            p = Runtime.getRuntime().exec(f.getPath());

            InputStream in = p.getInputStream() ;
            OutputStream out = p.getOutputStream ();
            InputStream err = p.getErrorStream();

            printOut = new PrintWriter(out);

            m_queue = new ArrayBlockingQueue<String>(10);
            inputThread = new InputThread(in, m_queue);
            inputThread.start();

        } catch(Exception e) { popup(e.getMessage()); }


        btn.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View view)
            {
                editText = (EditText)findViewById(R.id.editText1);
                input = editText.getText().toString();
// pass something to C binary
                printOut.println(input+"\n");
                printOut.flush();
            }
        });
    }

private void setTextHandler(final String text)
{
    Message msg = new Message();
    msg.obj = text;
    handler.sendMessage(msg);
}

private void mainLoop()
{
    String line;

    while(true)
    {
            try {
            line = bufIn.readLine();

// stdin is always empty... why?

            if(line != null) { setTextHandler(line); }
        }
        catch(IOException e) { popup(e.getMessage()); return; }
    }
}

private class InputThread extends Thread
{
    InputThread(InputStream in, BlockingQueue<String> queue)
    {
        bufIn = new BufferedReader(new InputStreamReader(in));
        m_queue = queue;
    }
    public void run() {

        try { mainLoop(); }

            catch(Throwable t) { popup(t.getMessage()); }
    }
}

}

UPDATE: if I compile the following C code:

#include <stdio.h>
#include <string.h>

int main(void)
{
char *s;

setvbuf(stdout, NULL, _IONBF, 0); // <<<= disable buffering globally

printf("Enter your name:\n");
fflush(stdout);
scanf("%s", &s);
printf("Hello, %s", s);
fflush(stdout);

return 0;
}

I get results only when binary exits, ie. I run android app, see a blank screen (must see "Enter your name:"), input something, press OK button - binary exits and I get "Enter your name: Hello, Eugene" at once.

PROBLEM SOLVED! See updated C code.

4
  • Do you only have the executable, or the source? If you have the C source, calling it by JNI would be the right way to do it. Commented Feb 11, 2013 at 0:54
  • @Eugene, what's the logcat output? Any errors/exceptions? Commented Feb 11, 2013 at 1:17
  • Sure, I have the C code. It's just a printf/scanf. How JNI helps me? Commented Feb 11, 2013 at 1:24
  • I just started learn Eclipse and I am not familiar with logcat yet ;( I run app directly on smartphone, there are no errors. Commented Feb 11, 2013 at 1:27

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.