Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 36 additions & 17 deletions app/src/main/java/com/httrack/android/HTTrackActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ protected static boolean isIPv6Enabled() {
* on a permission, nor on a volume being mounted.
*
* @param context
* null while the activity is being torn down, in which case nothing is written
* an app context; null is tolerated (nothing is written)
* @param e
* the throwable to record
*/
Expand Down Expand Up @@ -993,35 +993,37 @@ public void setParent(final HTTrackActivity parent) {
runner.execute();
}

// Is a live (non-ended) crawl still attached to this fragment?
public boolean hasLiveRunner() {
return runner != null && !runner.isEnded();
}

// Attach activity
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
final HTTrackActivity parent = HTTrackActivity.class.cast(activity);
// We expect the runner not to be null at this point.
if (runner != null) {
// Reclaimed across a configuration change: hand the live task its new activity.
runner.setParent(parent);
} else {
// We have to create the runner. Should not happen ?
Throwable trace;
try {
throw new RuntimeException();
} catch (final RuntimeException re) {
trace = re;
}
Log.w(
this.getClass().getSimpleName(),
"empty fragment attached to an activity, creating the associated runner",
trace);
setParent(parent);
// Restored empty after process death (setRetainInstance is a no-op there): the crawl is
// gone, so drop this stale fragment rather than auto-starting one the user never asked for.
Log.w(this.getClass().getSimpleName(),
"empty runner fragment restored after process death; discarding");
getParentFragmentManager().beginTransaction().remove(this)
.commitAllowingStateLoss();
}
}

// Detach activity
@Override
public void onDetach() {
super.onDetach();
runner.detach();
// Null after a discarded process-death restore, where no runner was ever created.
if (runner != null) {
runner.detach();
}
}

public boolean stopMirror(final boolean force) {
Expand All @@ -1041,6 +1043,8 @@ protected static class Runner extends AsyncTask<Void, Integer, Void>
private final HTTrackLib engine = new HTTrackLib(this);
final private StringBuilder str = new StringBuilder();
private HTTrackActivity parent;
// Application context, captured once and never detached, so a crash after detach() still dumps.
private final Context appContext;
private final List<Runnable> pendingParentActions = new ArrayList<Runnable>();
private boolean mirrorRefresh;
protected HTTrackStats lastStats;
Expand Down Expand Up @@ -1070,6 +1074,7 @@ protected static class Runner extends AsyncTask<Void, Integer, Void>
* the parent activity.
*/
public Runner(final HTTrackActivity parent) {
appContext = parent.getApplicationContext();
setParent(parent);
}

Expand Down Expand Up @@ -1138,7 +1143,7 @@ protected Void doInBackground(final Void... arg0) {
try {
runInternal();
} catch (final RuntimeException e) {
HTTrackActivity.emergencyDump(parent, e);
HTTrackActivity.emergencyDump(appContext, e);
throw e;
} finally {
ended = true;
Expand Down Expand Up @@ -1727,6 +1732,15 @@ protected void unserialize() throws IOException {
mapper.unserialize(profile);
}

/**
* Is a crawl still actually running? True only for a fragment reclaimed across a configuration
* change with a live, non-ended runner; false after process death (fragment restored empty).
*/
protected boolean hasLiveRunner() {
final Fragment f = getSupportFragmentManager().findFragmentByTag(sessionID);
return f instanceof RunnerFragment && ((RunnerFragment) f).hasLiveRunner();
}

/**
* Start the runner
*/
Expand Down Expand Up @@ -2922,8 +2936,13 @@ protected void restoreInstanceState(final Bundle savedInstanceState) {
// Load map settings
loadParcelable(data);

// The progress pane means a live crawl; after process death none exists, so land on the
// setup pane instead, where isInterruptedProfile() defaults the action to Continue.
final int paneId = (id == LAYOUT_MIRROR_PROGRESS && !hasLiveRunner())
? LAYOUT_PROJECT_SETUP : id;

// Switch pane id (0 by default)
setPane(id);
setPane(paneId);

// Set focus
setCurrentFocusId(focus_ids);
Expand Down
Loading