我正在编写一个运行无限 ping 的应用程序,使用系统命令 /system/bin/ping 来测量网络状态。
为了处理正在运行的线程,我使用了 Fragment。因此在屏幕旋转或屏幕锁定期间该进程仍在运行。当我按下返回按钮或主页按钮时,该应用程序似乎运行良好。但是当我用最近的应用程序杀死应用程序时,即使主应用程序关闭,线程仍在运行。
当然,我可以使用 -c 选项限制 ping 的数量,但我想在应用程序关闭后立即停止线程。
有没有办法知道一个应用程序使用最近的应用程序被杀死?
我应该使用 Fragment / AsyncTask 以外的其他方式来处理这种类型的线程吗?
谢谢您的帮助
主类:
public class MainActivity extends Activity implements PingFragment.PingTaskCallbacks {
/* Fragment used to manage the ping task*/
private PingFragment mPingFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getFragmentManager();
mPingFragment = (PingFragment) fm.findFragmentByTag("ping");
// If the Fragment is non-null, then it is currently being
// retained across a configuration change.
if (mPingFragment == null) {
mPingFragment = new PingFragment();
fm.beginTransaction().add(mPingFragment, "ping").commit();
}//endIf
...
}//endFct
@Override
protected void onResume() {
super.onResume();
}//endFct
@Override
protected void onPause() {
super.onPause();
}//endFct
public void doPing() {
String url = "www.google.com";
mPingFragment.startPing(url);
}
public void stopPing() {
mPingFragment.stopPing();
}
@Override
public void onProgressUpdate(String aPingLine) {
// method called on every ping
}
}
片段类:
public class PingFragment extends Fragment {
/**
* Callback interface through which the fragment will report the
* task's progress and results back to the Activity.
*/
static interface PingTaskCallbacks {
void onProgressUpdate(String aPingLine);
}//endIntf
private PingTaskCallbacks mCallbacks;
private PingTask mTask;
/**
* This method will only be called once when the retained
* Fragment is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
setRetainInstance(true);
}
/**
* Hold a reference to the parent Activity so we can report the
* task's current progress and results. The Android framework
* will pass us a reference to the newly created Activity after
* each configuration change.
*/
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallbacks = (PingTaskCallbacks) activity;
}
/**
* Set the callback to null so we don't accidentally leak the
* Activity instance.
*/
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("PingFragment.onDestroy()", "*** Fragment call destroy ***");
stopPing();
}
public void startPing(String url) {
if (mTask != null && ! mTask.getStatus().equals(AsyncTask.Status.FINISHED)) {
mTask.stop();
}//endIf
// Create and execute the background task.
mTask = new PingTask();
mTask.execute(url);
}
public void stopPing() {
mTask.stop();
mTask = null;
}
/**
* A task that performs some ping in background.
*
* Note that we need to check if the callbacks are null in each
* method in case they are invoked after the Activity's and
* Fragment's onDestroy() method have been called.
*/
private class PingTask extends AsyncTask<String, String, Void> {
private PipedOutputStream mPOut;
private PipedInputStream mPIn;
private LineNumberReader mReader;
private Process mProcess;
@Override
protected void onPreExecute() {
mPOut = new PipedOutputStream();
try {
mPIn = new PipedInputStream(mPOut);
mReader = new LineNumberReader(new InputStreamReader(mPIn));
} catch (IOException e) {
cancel(true);
}//endTry
}//endF
/**
* Note that we do NOT call the callback object's methods
* directly from the background thread, as this could result
* in a race condition.
*/
@Override
protected Void doInBackground(String... params) {
String aLine = "";
try {
mProcess = new ProcessBuilder()
.command("/system/bin/ping", params[0])
.redirectErrorStream(true)
.start();
try {
InputStream in = mProcess.getInputStream();
OutputStream out = mProcess.getOutputStream();
byte[] buffer = new byte[1024];
int count;
// in -> buffer -> mPOut -> mReader -> 1 line of ping information to parse
while ((count = in.read(buffer)) != -1) {
mPOut.write(buffer, 0, count);
while (mReader.ready()) {
aLine = mReader.readLine();
publishProgress(aLine);
}//endWhile
if (isCancelled()) {
stop();
break;
}//endIf
}//endWhile
out.close();
in.close();
mPOut.close();
mPIn.close();
} finally {
stop();
}//endTry
} catch (IOException e) {
}//endTry
return null;
}//endFct
@Override
protected void onProgressUpdate(String... aPingLine) {
if (mCallbacks != null) {
mCallbacks.onProgressUpdate(aPingLine[0]);
}//endIf
}//endFct
public void stop() {
if (mProcess != null) {
mProcess.destroy();
mProcess = null;
}//endIf
cancel(true);
}//endStop
}
}