Android- Error during executing Runtime.getRuntime

2019-04-13 08:54发布

问题:

I have compiled ffmpeg library on ubuntu 11.10 and ported compiled files on android.
After compiling i got libffmpeg.so successfully. It gets loaded on android successfully.

I am doing it on ubuntu 11.10 eclipse android emulator.

I have created a small test application which act as command prompt which accepts command from user and displays result. (testing ffmpeg commands)

When i run simple commands like "ls", "ls -l" it works perfectly. but when i simply type "cd mnt" or "ffmpeg" as command and try to run it. I got Warnings in Logcat saying that

08-26 16:44:52.553: W/System.err(5961): java.io.IOException: Error running exec(). Command: [ffmpeg] Working Directory: null Environment: null
08-26 16:44:52.573: W/System.err(5961):     at java.lang.ProcessManager.exec(ProcessManager.java:211)
08-26 16:44:52.573: W/System.err(5961):     at java.lang.Runtime.exec(Runtime.java:168)
08-26 16:44:52.573: W/System.err(5961):     at java.lang.Runtime.exec(Runtime.java:241)
08-26 16:44:52.583: W/System.err(5961):     at java.lang.Runtime.exec(Runtime.java:184)
08-26 16:44:52.593: W/System.err(5961):     at ch.ffmpeg.reversit.MainActivity.Execute(MainActivity.java:61)
08-26 16:44:52.593: W/System.err(5961):     at ch.ffmpeg.reversit.MainActivity$1.onClick(MainActivity.java:46)
08-26 16:44:52.593: W/System.err(5961):     at android.view.View.performClick(View.java:3480)
08-26 16:44:52.593: W/System.err(5961):     at android.view.View$PerformClick.run(View.java:13983)
08-26 16:44:52.603: W/System.err(5961):     at android.os.Handler.handleCallback(Handler.java:605)
08-26 16:44:52.603: W/System.err(5961):     at android.os.Handler.dispatchMessage(Handler.java:92)
08-26 16:44:52.603: W/System.err(5961):     at android.os.Looper.loop(Looper.java:137)
08-26 16:44:52.614: W/System.err(5961):     at android.app.ActivityThread.main(ActivityThread.java:4340)
08-26 16:44:52.624: W/System.err(5961):     at java.lang.reflect.Method.invokeNative(Native Method)
08-26 16:44:52.624: W/System.err(5961):     at java.lang.reflect.Method.invoke(Method.java:511)
08-26 16:44:52.634: W/System.err(5961):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-26 16:44:52.634: W/System.err(5961):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-26 16:44:52.644: W/System.err(5961):     at dalvik.system.NativeStart.main(Native Method)
08-26 16:44:52.644: W/System.err(5961): Caused by: java.io.IOException: Permission denied
08-26 16:44:52.674: W/System.err(5961):     at java.lang.ProcessManager.exec(Native Method)
08-26 16:44:52.674: W/System.err(5961):     at java.lang.ProcessManager.exec(ProcessManager.java:209)
08-26 16:44:52.684: W/System.err(5961):     ... 16 more

Here is my code :

imports;
public class MainActivity extends Activity {
    String com;
    Process process;
    EditText command;
    Button run;
    RelativeLayout main_layout;

    static {
     System.loadLibrary("ffmpeg");
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       //find view 
       command=(EditText)findViewById(R.id.command);
       run=(Button)findViewById(R.id.run);

        run.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                com=command.getText().toString();
                try {
                    Execute();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }); 

    }

    public void Execute() throws IOException, InterruptedException{
        process=Runtime.getRuntime().exec(com);
        // process = pb.command(com).redirectErrorStream(true).start();

        if(process!=null)
        ShowOutput();
        else
        Toast.makeText(getBaseContext(),"Null Process",Toast.LENGTH_LONG).show();
    }

    public void ShowOutput() throws IOException, InterruptedException{
        String s,text="",errors="";
        BufferedReader stdInput = new BufferedReader(new 
                InputStreamReader(process.getInputStream()));

           BufferedReader stdError = new BufferedReader(new 
                InputStreamReader(process.getErrorStream()));


           TextView output=(TextView)findViewById(R.id.output);
           TextView error=(TextView)findViewById(R.id.error);

            while ((s = stdInput.readLine()) != null) {
                   text+=s.toString()+"\n";
                   System.out.println("Error: "+s);
               }

         output.setText(text);
         text="";
           // read any errors from the attempted command
           System.out.println("Here is the standard error of the command (if any):\n");
           while ((s = stdError.readLine()) != null) {
               text+=s.toString()+"\n";
               System.out.println("Error: "+s);
           }

           error.setText(text);

           error.setMovementMethod(new ScrollingMovementMethod());
           output.setMovementMethod(new ScrollingMovementMethod());

           stdInput.close();
           stdError.close();

           process.waitFor();
           process.getOutputStream().close();
           process.getInputStream().close();
           process.getErrorStream().close(); 
           process.destroy();


    }

}

I even tried process = pb.command(com).redirectErrorStream(true).start(); for execution. It gives me same error but this time environment was [ANDROID_SOCKET_Zygot] bla bla bla..


EDIT 1: I use Openjdk on ubuntu

Help me out !!

回答1:

There is a pretty large body of [android] [ffmpeg] discussion and how to's...

The normal way to invoke ffmpeg on non-rooted devices ( ie app for general users ) is to use the NDK and a C-lang integration where in java you make a normal method call that wraps the CLI stuff and the collection of parms that the JNI layer will deliver to the interface of the ffmpeg executable.

Example of the android call step1.android would be...

             new FFMpegTask().execute(invoke_lib_path,"ffmpeg", "-y", 
                    "-i", Picture.getPath(), "-i", recordFilePath,
                    "-vcodec", "mpeg4", "-s", siz,
                    "-r", "15", "-b:v", "200k",
                    "-acodec", "copy", "-f", "3gp"
                    ,pathOut);

Step2.c

JNIEXPORT void JNICALL Java_com_..._naRun( JNIEnv *env, jobject obj, jobjectArray args) { int i = 0; int argc = 0; char **argv = NULL;

if (args != NULL) { argc = (env)->GetArrayLength(env, args); argv = (char *) malloc(sizeof(char *) * argc);

  for(i=0;i<argc;i++)         {           jstring str =

(jstring)(*env)->GetObjectArrayElement(env, args, i); argv[i] = (char *)(*env)->GetStringUTFChars(env, str, NULL); } } int j = 0; j = main(argc, argv); }

Trying to use java runtime.exec() type CLI call is what i would call a hack that will be a big waste of your time.

By using the NDK and the normal packaging in an .apk, you are assuring a higher degree of reliability and integration between things like the processor architecture on the deploy device and the processor that ffmpeg was built for.

try reading roman10's intro

Then you might try relying on the breadcrumbs from lots of people who have built ffmpeg for android .. ie google "android-ffmpeg"

If you are rooted and you have compiled an executable then you can invoke that by getting a shell and using the adb CLI. Note that is not like using java as a wrapper for runtime.exec calls.

adb push ffmpeg /data/local/ffmpeg/ffmpeg

./ffmpeg -codecs



回答2:

AFAIK You cannot use cd command. It is a bash directive, there is no executable cd. I guess ffmpeg is not working because of permissions. On adb shell do chmod 777 ffmpeg and try again



回答3:

I might be little bit late

java.io.IOException: Error running exec(). Command: [ffmpeg] Working Directory: null Environment: null

It is clearly mentioned that ffmpeg file is not found . Before exexuting any command first check If File is present in the mentioned location.

boolean ifFileExists = new File(*path_of_ffmpeg_file*).exists();


       if(ifFileExists==false){
// code to write file in phone
    }
method(commandToExecute);