需求是在應用中執行版本腳本,且只執行一次。需要用到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應用開發中,如何執行腳本文件的解決方案。最後慣例給大家推介一下我們的技術工作號,歡迎大家來交流技術問題,謝謝!