
com.android.utils.GrabProcessOutput Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of common Show documentation
Show all versions of common Show documentation
common library used by other Android tools libraries.
The newest version!
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.utils;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.google.common.io.Closeables;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class GrabProcessOutput {
public enum Wait {
/**
* Doesn't wait for the exec to complete.
* This still monitors the output but does not wait for the process to finish.
* In this mode the process return code is unknown and always 0.
*/
ASYNC,
/**
* This waits for the process to finish.
* In this mode, {@link GrabProcessOutput#grabProcessOutput} returns the
* error code from the process.
*
* In some rare cases and depending on the OS, the process might not have
* finished dumping data into stdout/stderr.
*
* Use this when you don't particularly care for the output but instead
* care for the return code of the executed process.
*/
WAIT_FOR_PROCESS,
/**
*
* This waits for the process to finish and for the stdout/stderr
* threads to complete.
* In this mode, {@link GrabProcessOutput#grabProcessOutput} returns the
* error code from the process.
*
* Use this one when capturing all the output from the process is important.
*/
WAIT_FOR_READERS,
}
public interface IProcessOutput {
/**
* Processes an stdout message line.
* @param line The stdout message line. Null when the reader reached the end of stdout.
*/
void out(@Nullable String line);
/**
* Processes an stderr message line.
* @param line The stderr message line. Null when the reader reached the end of stderr.
*/
void err(@Nullable String line);
}
/**
* Get the stderr/stdout outputs of a process and return when the process is done.
* Both must be read or the process will block on windows.
*
* @param process The process to get the output from.
* @param output Optional object to capture stdout/stderr.
* Note that on Windows capturing the output is not optional. If output is null
* the stdout/stderr will be captured and discarded.
* @param waitMode Whether to wait for the process and/or the readers to finish.
* @return the process return code.
* @throws InterruptedException if {@link Process#waitFor()} was interrupted.
*/
public static int grabProcessOutput(
@NonNull final Process process,
Wait waitMode,
@Nullable final IProcessOutput output) throws InterruptedException {
// read the lines as they come. if null is returned, it's
// because the process finished
Thread threadErr = new Thread("stderr") {
@Override
public void run() {
// create a buffer to read the stderr output
InputStream is = process.getErrorStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader errReader = new BufferedReader(isr);
try {
while (true) {
String line = errReader.readLine();
if (output != null) {
output.err(line);
}
if (line == null) {
break;
}
}
} catch (IOException e) {
// do nothing.
} finally {
try {
Closeables.close(is, true /* swallowIOException */);
} catch (IOException e) {
// cannot happen
}
try {
Closeables.close(isr, true /* swallowIOException */);
} catch (IOException e) {
// cannot happen
}
try {
Closeables.close(errReader, true /* swallowIOException */);
} catch (IOException e) {
// cannot happen
}
}
}
};
Thread threadOut = new Thread("stdout") {
@Override
public void run() {
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader outReader = new BufferedReader(isr);
try {
while (true) {
String line = outReader.readLine();
if (output != null) {
output.out(line);
}
if (line == null) {
break;
}
}
} catch (IOException e) {
// do nothing.
} finally {
try {
Closeables.close(is, true /* swallowIOException */);
} catch (IOException e) {
// cannot happen
}
try {
Closeables.close(isr, true /* swallowIOException */);
} catch (IOException e) {
// cannot happen
}
try {
Closeables.close(outReader, true /* swallowIOException */);
} catch (IOException e) {
// cannot happen
}
}
}
};
threadErr.start();
threadOut.start();
if (waitMode == Wait.ASYNC) {
return 0;
}
// it looks like on windows process#waitFor() can return
// before the thread have filled the arrays, so we wait for both threads and the
// process itself.
if (waitMode == Wait.WAIT_FOR_READERS) {
try {
threadErr.join();
} catch (InterruptedException e) {
}
try {
threadOut.join();
} catch (InterruptedException e) {
}
}
// get the return code from the process
return process.waitFor();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy