import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Scanner;
import android.content.res.AssetManager;
import android.os.Build;
import android.util.Log;
public class ShellUtils
{
private static String busyboxPath="/system/xbin/busybox";
/**
* Set custom busybox path
* @param path Path
*/
public static void setCustomBusybox(String path){
busyboxPath = path;
}
public static boolean checkBusyboxPath(){
try{
if (!new File("/system/xbin/busybox").exists()){
if(!new File("/system/bin/busybox").exists())
return false;
else busyboxPath="/system/bin/busybox";
}
else busyboxPath="/system/xbin/busybox";
}catch (SecurityException e){
return false;
}
return true;
}
/**
* Try to get root permission
* @return true means success; false means fail
*/
public static boolean rootCheck(){
//List all the files under "/data/data", doing this operation needs root permission
//CommandResult commandResult = execCommand(false,true, "ls /data/data/");
//Empty result means there's no root permission
//return !commandResult.successMsg.isEmpty();
return execCommand(false,true,"").result==0;
}
@SuppressWarnings("deprecation")
public static boolean initiateBusybox(){
//Clear old files
File busybox = new File(GlobalVariable.getContext().getFilesDir()+"/busybox");
if (busybox.exists())
busybox.delete();
//Copy corresponding busybox to internal folder
String cpuVersion;
if (android.os.Build.VERSION.SDK_INT <21)
cpuVersion= Build.CPU_ABI;
else
cpuVersion=Build.SUPPORTED_ABIS[0];
//Determine busybox version
String filename;
cpuVersion=cpuVersion.toLowerCase();
if (cpuVersion.contains("arm"))
filename="busybox-armv5l";
else if (cpuVersion.contains("x86"))
filename="busybox-i686";
else
return false;
AssetManager assetManager = GlobalVariable.getContext().getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
out = new FileOutputStream(busybox);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
catch (IOException e) {
e.printStackTrace();
return false;
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//Make busybox executables
ShellUtils.execCommand(false, true, "chmod 0755 " + GlobalVariable.getContext().getFilesDir() + "/busybox");
return true;
}
/**
* Execute commands and get the results
* @param isBusybox Run cmds via busybox or not
* @param isRoot Run cmds as root?
* @param cmds Command(s)
* @return Results of commands
*/
public static CommandResult execCommand(boolean isBusybox, boolean isRoot, String...cmds){
int result=-1;
StringBuilder successMsg = null;
StringBuilder errorMsg = null;
if (cmds==null || cmds.length==0)
return new CommandResult(result,null,null);
try{
Process proc=Runtime.getRuntime().exec(isRoot?"su":"sh");
DataOutputStream opt = new DataOutputStream(proc.getOutputStream());
boolean exitCmdFound=false;
//Write cmds
for(String cmd:cmds){
//Using busybox and check its path
if (isBusybox)
opt.writeBytes(busyboxPath + " ");
//Unless make sure cmd is in English, using UTF-8 coding, avoid wrong coding.
opt.write(cmd.getBytes(Charset.forName("utf-8")));
if(!exitCmdFound && cmd.equals("exit"))
exitCmdFound=true;
opt.writeBytes("\n");
}
if(!exitCmdFound)
opt.writeBytes("exit\n");
opt.flush();
//Get results
result=proc.waitFor();
successMsg = new StringBuilder();
errorMsg = new StringBuilder();
Scanner scanner;
scanner=new Scanner(new InputStreamReader(proc.getInputStream()));
while (scanner.hasNextLine())
successMsg.append(scanner.nextLine());
scanner=new Scanner(new InputStreamReader(proc.getErrorStream()));
while (scanner.hasNextLine())
errorMsg.append(scanner.nextLine());
} catch (Exception e){
e.printStackTrace();
}
return new CommandResult(result,successMsg==null?null:successMsg.toString(), errorMsg==null?null:errorMsg.toString());
}
public static class CommandResult {
/**
* Result of command
* 0: normal
* else: error
*/
public int result;
public String successMsg;
public String errorMsg;
public CommandResult(int result, String successMsg, String errorMsg) {
this.result = result;
this.successMsg = successMsg;
this.errorMsg = errorMsg;
}
}
}