需求是在应用中执行版本脚本,且只执行一次。需要用到su权限、资源文件获取等等知识点。
基本思路
- 对比版本信息
- 将资源文件中的版本脚本写入到应用目录中
- 给脚本执行权限
- 执行脚本
对比版本信息
主要思路是:执行成功完成后将版本写入到数据库中去。下次执行时再对比版本信息是否一致。
资源文件写入到应用目录
获取资源文件我采用的是:mContext.getAssets().open("versionShell.sh");
需要注意的是:assets需要放到main目录下,否则会报找不到文件的错误。
/**
* 将资源文件中的sh脚本写到应用目录
*/
private void writeFileToData() {
OutputStream output = null;
InputStream input = null;
try {
File shellPath = new File(mContext.getFilesDir(), SHELL_FILE_NAME);
output = new FileOutputStream(shellPath);
input = mContext.getAssets().open(SHELL_FILE_NAME);
int count;
int off = 0;
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
output.write(data, off, count);
off += count;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (output != null) {
output.close();
output = null;
}
if (input != null) {
input.close();
input = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行脚本
1、普通权限执行命令
/**
* 普通权限执行
* @param cmd
*/
private void exec(String cmd) {
Runtime mRuntime = Runtime.getRuntime();
BufferedReader mReader = null;
try {
//Process中封装了返回的结果和执行错误的结果
Process mProcess = mRuntime.exec(cmd);
Logger.d(TAG, "exec cmd : " + cmd);
mReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
StringBuffer mRespBuff = new StringBuffer();
char[] buff = new char[1024];
int ch = 0;
while ((ch = mReader.read(buff)) != -1) {
mRespBuff.append(buff, 0, ch);
}
Logger.d(TAG, mRespBuff.toString());
} catch (IOException e) {
Logger.e(TAG, "exec error: "+ e.toString());
}finally {
try{
if(mReader != null){
mReader.close();
mReader = null;
}
}catch (IOException e){
Logger.e(TAG, "exec error: "+ e.toString());
}
}
}
2、su权限执行命令
包含了多条命令执行。
/**
* su权限执行命令
* @param fileName
* @return
*/
public boolean runShellFile(String fileName) {
boolean result = false;
DataOutputStream dataOutputStream = null;
BufferedReader mReader = null;
try {
Process process = Runtime.getRuntime().exec("su");
dataOutputStream = new DataOutputStream(process.getOutputStream());
String cmd = "cd " + mContext.getFilesDir()+"\n";
dataOutputStream.write(cmd.getBytes(Charset.forName("utf-8")));
dataOutputStream.flush();
cmd = "chmod +x " + fileName+"\n";
dataOutputStream.writeBytes(cmd);
dataOutputStream.flush();
//清理文本编码不对导致有后缀的问题
cmd = "dos2unix " + fileName+"\n";
dataOutputStream.writeBytes(cmd);
dataOutputStream.flush();
cmd = "./" + fileName +"\n";
dataOutputStream.writeBytes(cmd);
dataOutputStream.flush();
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
//获取结果
process.waitFor();
mReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String msg = "";
String line;
while ((line = mReader.readLine()) != null) {
msg += line;
}
Logger.d(TAG, " read msg: " + msg);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (dataOutputStream != null) {
dataOutputStream.close();
}
if (mReader != null) {
mReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
注意点1:没有返回值的时候会卡顿在readLine读取返回值的地方。
注意点2:su权限执行后,需要执行exit退出后才能获取到返回值。
源码
结束语
以上就是本次分享的android应用开发中,如何执行脚本文件的解决方案。最后惯例给大家推介一下我们的技术工作号,欢迎大家来交流技术问题,谢谢!