Android- Error during executing Runtime.getRuntime().exec() - Environment Null -ffmpeg
Asked Answered
S

3

2

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 !!

Shortwave answered 26/8, 2012 at 11:42 Comment(0)
D
2

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

Discontinuation answered 26/8, 2012 at 16:48 Comment(5)
yes. as an example, u can just get the code from the link mentioned in roman10 blog. there are alot of other, newer android-ffmpeg projects on github. just search there for android-ffmpeg. u can clone one of those and build it following instructions in README.Discontinuation
from which directory i shoukld be running adb push ffmpeg?? i didn't fing my ffmpeg binaries through adb. Can you tell me from where can i find it?Shortwave
Project$ ls -l libs/armeabi-v7a/ is ans on my system. Your toolchain determines the output location. if u use NDK then read the docs in ./docs. If u are using ndk then add "V=1 -B"Discontinuation
ok in my case lib/armeabi-v7a contains only libffmpeg.so file. so i need whole binaries (ffmpeg folder) to be pushed in right?Shortwave
ok. your Android.mk file is only creating shared-modules . change it to create an executable and then u will find that in the folder u mention. RTM...Discontinuation
H
1

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

Hillery answered 26/8, 2012 at 12:32 Comment(4)
hey.. can you please tell me for which directory or library should i run this command. i tried from adb shell but it says no such directory.Shortwave
find where ffmpeg is present , it might be in system/bin , so you can go there and do it. Even in code use /system/bin/ffmpegHillery
i searched !! but there is no directory called ffmpeg. ffmpeg is actually a native library. i have compiled libffmpeg.so which supposed to give me ffmpeg support.Shortwave
github.com/halfninja/android-ffmpeg-x264/blob/master/Project/… look at the diff lines (18 vs 34) . If u need executable specify that. If u need shared lib specify that.... read the docs on Android.mk in ./NDK_ROOT/docsDiscontinuation
D
0

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);
Damalis answered 18/2, 2015 at 4:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.