这是我的onCreate的一部分,有时会导致异常:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tilisting);
_context = getApplicationContext();
SDName = Environment.getExternalStorageDirectory();
//listview = (ListView)findViewById(R.id.TIlistview);
String TIdir = new File(SDName, "/TitaniumBackup/").toString();
final ArrayList<String> apps = new ArrayList<String>();
final StringBuffer done = new StringBuffer();
Command command = new Command(0,"ls -a "+TIdir+"/*.properties") {
@Override
public void output(int arg0, String arg1) {
synchronized(apps) {
apps.add(arg1);
if (!done.toString().equals("")) {
done.append("done");//oh no
}
}
}
};
try {
RootTools.getShell(true).add(command).waitForFinish();
String attrLine = "";
int ind;
backups = new ArrayList<TIBackup>();
synchronized(apps) {
for (String app : apps) {
try {
TIBackup bkup = new TIBackup(app);
FileInputStream fstream = new FileInputStream(app);
BufferedReader atts = new BufferedReader(new InputStreamReader(fstream));
while ((attrLine = atts.readLine()) != null) {
ind = attrLine.indexOf('=');
if (ind !=-1 && !attrLine.substring(0,1).equals("#"))
bkup.prop.put(attrLine.substring(0,ind), attrLine.substring(ind+1));
}
backups.add(bkup);
atts.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
done.append("done");
}
setListAdapter( new StableArrayAdapter(this,backups));
} catch (InterruptedException e) {
//TODO:errors
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
for (String app : apps) {
导致异常,尽管之前有waitforfinish()。
这个更新的代码应该修复它,从输出中添加数据,并等待主代码中具有synchronized的任何straggler,但是如果你在上面的//哦没有行设置一个断点,它仍然是这个在UI主代码运行后尝试添加项目的位置。那么waitforfinish()是不是在等待?我如何防止这种竞争状况?
我也试过下面的RootTask
代码,但它似乎停在最后一条读取线上了?
RootTask getProfile = new RootTask() {
@Override
public void onPostExecute(ArrayList<String> result) {
super.onPostExecute(result);
for (String r : result) {
System.out.println(r);
}
}
};
getProfile.execute("ls /data/data/org.mozilla.firefox/files/mozilla/" );
onPostExecute永远不会运行。
答案 0 :(得分:1)
Output()
等待期间, waitForFinish()
将被称为。实现Command执行的代码有问题。
最有可能的是:命令执行器(RootTools
?)在shell上运行命令,获取一堆输出行,通知调用线程等待,然后然后调用{{1它作为输出获得的每一行的命令。对于所有输出行,我认为应该在命令对象上调用 output()
之后通知命令线程。
仍然可以包装列表修改代码并列出output()
中的迭代代码。
更新:
所以
synchronized(<some common object>){}
还没有等待?我如何防止这种竞争状况?
它确实等待,但不是你的代码。 waitForFinish()
关键字只是确保在您迭代Synchronized
集合时不会同时调用output()
Command
个apps
对象。它不安排两个线程按特定顺序运行。
恕我直言,waitForFinish()
不是一个好模式,使调用线程等待失败了一个单独的执行者。最好像AsyncTask
那样表达,或者为每个Command
对象接受一个事件监听器。
只是一个粗略的例子,这个类:
public class RootTask extends AsyncTask<String,Void,List<String>> {
private boolean mSuccess;
public boolean isSuccess() {
return mSuccess;
}
@Override
protected List<String> doInBackground(String... strings) {
List<String> lines = new ArrayList<String>();
try {
Process p = Runtime.getRuntime().exec("su");
InputStream is = p.getInputStream();
OutputStream os = p.getOutputStream();
os.write((strings[0] + "\n").getBytes());
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = rd.readLine()) != null){
lines.add(line);
}
mSuccess = true;
os.write(("exit\n").getBytes());
p.destroy();
} catch (IOException e) {
mSuccess = false;
e.printStackTrace();
}
return lines;
}
}
可以用作:
RootTask listTask = new RootTask{
@Override
public void onPostExecute(List<String> result){
super.onPostExecute();
apps.addAll(result);
//-- or process the results strings--
}
};
listTask.execute("ls -a "+TIdir+"/*.properties");
答案 1 :(得分:1)
这部分是由RootTools中的设计缺陷引起的。我相信问题的关键在于,您在shell上执行的操作所花费的时间比为shell命令设置的默认超时要长。当超时发生时,它只返回完成的命令,这是设计缺陷所在。
我提供了一个新的jar以及更多相关信息。我也弃用了waitForFinish(),因为我同意这是一个糟糕的解决方案。
https://code.google.com/p/roottools/issues/detail?id=35
如果您有任何疑问或问题,请告诉我。)