diff options
Diffstat (limited to 'app/src/main/java')
5 files changed, 353 insertions, 26 deletions
| diff --git a/app/src/main/java/org/connectbot/EditHostActivity.java b/app/src/main/java/org/connectbot/EditHostActivity.java index 6c7da11..f61924f 100644 --- a/app/src/main/java/org/connectbot/EditHostActivity.java +++ b/app/src/main/java/org/connectbot/EditHostActivity.java @@ -17,27 +17,236 @@  package org.connectbot; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.res.TypedArray; +import android.os.AsyncTask; +import android.os.IBinder; +import android.support.v4.app.FragmentManager;  import android.support.v7.app.AppCompatActivity;  import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem;  import org.connectbot.bean.HostBean; +import org.connectbot.service.TerminalBridge; +import org.connectbot.service.TerminalManager; +import org.connectbot.util.HostDatabase; +import org.connectbot.util.PubkeyDatabase;  public class EditHostActivity extends AppCompatActivity implements HostEditorFragment.Listener { +	private static final String EXTRA_EXISTING_HOST_ID = "org.connectbot.existing_host_id"; +	private static final long NO_HOST_ID = -1; + +	private HostDatabase mHostDb; +	private PubkeyDatabase mPubkeyDb; +	private ServiceConnection mTerminalConnection; +	private HostBean mHost; +	private TerminalBridge mBridge; +	private boolean mIsCreating; +	private MenuItem mSaveHostButton; + +	public static Intent createIntentForExistingHost(Context context, long existingHostId) { +		Intent i = new Intent(context, EditHostActivity.class); +		i.putExtra(EXTRA_EXISTING_HOST_ID, existingHostId); +		return i; +	} + +	public static Intent createIntentForNewHost(Context context) { +		return createIntentForExistingHost(context, NO_HOST_ID); +	} +  	@Override  	protected void onCreate(Bundle savedInstanceState) {  		super.onCreate(savedInstanceState); + +		mHostDb = HostDatabase.get(this); +		mPubkeyDb = PubkeyDatabase.get(this); + +		mTerminalConnection = new ServiceConnection() { +			public void onServiceConnected(ComponentName className, IBinder service) { +				TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService(); +				mBridge = bound.getConnectedBridge(mHost); +			} + +			public void onServiceDisconnected(ComponentName name) { +				mBridge = null; +			} +		}; + +		long hostId = getIntent().getLongExtra(EXTRA_EXISTING_HOST_ID, NO_HOST_ID); +		mIsCreating = hostId == NO_HOST_ID; +		mHost = mIsCreating ? null : mHostDb.findHostById(hostId); + +		// Note that the lists must be explicitly declared as ArrayLists because Bundle only accepts +		// ArrayLists of Strings. +		ArrayList<String> pubkeyNames = new ArrayList<>(); +		ArrayList<String> pubkeyValues = new ArrayList<>(); + +		// First, add default pubkey names and values (e.g., "use any" and "don't use any"). +		TypedArray defaultPubkeyNames = getResources().obtainTypedArray(R.array.list_pubkeyids); +		for (int i = 0; i < defaultPubkeyNames.length(); i++) { +			pubkeyNames.add(defaultPubkeyNames.getString(i)); +		} +		TypedArray defaultPubkeyValues = getResources().obtainTypedArray(R.array.list_pubkeyids_value); +		for (int i = 0; i < defaultPubkeyValues.length(); i++) { +			pubkeyValues.add(defaultPubkeyValues.getString(i)); +		} + +		// Now, add pubkeys which have been added by the user. +		for (CharSequence cs : mPubkeyDb.allValues(PubkeyDatabase.FIELD_PUBKEY_NICKNAME)) { +			pubkeyNames.add(cs.toString()); +		} +		for (CharSequence cs : mPubkeyDb.allValues("_id")) { +			pubkeyValues.add(cs.toString()); +		} +  		setContentView(R.layout.activity_edit_host); +		FragmentManager fm = getSupportFragmentManager(); +		HostEditorFragment fragment = +				(HostEditorFragment) fm.findFragmentById(R.id.fragment_container); -		if (savedInstanceState == null) { -			HostEditorFragment editor = HostEditorFragment.newInstance(null); +		if (fragment == null) { +			fragment = HostEditorFragment.newInstance(mHost, pubkeyNames, pubkeyValues);  			getSupportFragmentManager().beginTransaction() -					.add(R.id.fragment_container, editor).commit(); +					.add(R.id.fragment_container, fragment).commit();  		} + +		defaultPubkeyNames.recycle(); +		defaultPubkeyValues.recycle(); +	} + +	@Override +	public boolean onCreateOptionsMenu(Menu menu) { +		MenuInflater inflater = getMenuInflater(); +		inflater.inflate( +				mIsCreating ? R.menu.edit_host_activity_add_menu : R.menu.edit_host_activity_edit_menu, +				menu); + +		mSaveHostButton = menu.getItem(0); + +		// If the new host is being created, it can't be added until modifications have been made. +		mSaveHostButton.setEnabled(!mIsCreating); + +		return super.onCreateOptionsMenu(menu);  	}  	@Override -	public void onHostUpdated(HostBean host) { +	public boolean onOptionsItemSelected(MenuItem item) { +		switch (item.getItemId()) { +			case R.id.save: +				mHostDb.saveHost(mHost); + +				if (mBridge != null) { +					// If the console is already open, apply the new encoding now. If the console +					// was not yet opened, this will be applied automatically when it is opened. +					mBridge.setCharset(mHost.getEncoding()); +				} +				finish(); +				return true; +			default: +				return super.onOptionsItemSelected(item); +		} +	} +	@Override +	public void onStart() { +		super.onStart(); + +		bindService(new Intent( +				this, TerminalManager.class), mTerminalConnection, Context.BIND_AUTO_CREATE); + +		final HostEditorFragment fragment = (HostEditorFragment) getSupportFragmentManager(). +				findFragmentById(R.id.fragment_container); +		if (CharsetHolder.isInitialized()) { +			fragment.setCharsetData(CharsetHolder.getCharsetData()); +		} else { +			// If CharsetHolder is uninitialized, initialize it in an AsyncTask. This is necessary +			// because Charset must touch the disk, which cannot be performed on the UI thread. +			AsyncTask<Void, Void, Void> charsetTask = new AsyncTask<Void, Void, Void>() { + +				@Override +				protected Void doInBackground(Void... unused) { +					CharsetHolder.initialize(); +					return null; +				} + +				@Override +				protected void onPostExecute(Void unused) { +					fragment.setCharsetData(CharsetHolder.getCharsetData()); +				} +			}; +			charsetTask.execute(); +		} +	} + +	@Override +	public void onStop() { +		super.onStop(); + +		unbindService(mTerminalConnection); +	} + +	@Override +	public void onValidHostConfigured(HostBean host) { +		mHost = host; +		if (mSaveHostButton != null) +			mSaveHostButton.setEnabled(true); +	} + +	@Override +	public void onHostInvalidated() { +		mHost = null; +		if (mSaveHostButton != null) +			mSaveHostButton.setEnabled(false); +	} + +	// Private static class used to generate a list of available Charsets. Note that this class +	// must not be initialized by the UI thread because it blocks on disk access. +	private static class CharsetHolder { +		private static boolean mInitialized = false; + +		// Map from Charset display name to Charset value (i.e., unique ID). +		private static Map<String, String> mData; + +		public static Map<String, String> getCharsetData() { +			if (mData == null) +				initialize(); + +			return mData; +		} + +		private synchronized static void initialize() { +			if (mInitialized) +				return; + +			mData = new HashMap<>(); +			for (Map.Entry<String, Charset> entry : Charset.availableCharsets().entrySet()) { +				Charset c = entry.getValue(); +				if (c.canEncode() && c.isRegistered()) { +					String key = entry.getKey(); +					if (key.startsWith("cp")) { +						// Custom CP437 charset changes. +						mData.put("CP437", "CP437"); +					} +					mData.put(c.displayName(), entry.getKey()); +				} +			} + +			mInitialized = true; +		} + +		public static boolean isInitialized() { +			return mInitialized; +		}  	}  } diff --git a/app/src/main/java/org/connectbot/HostEditorFragment.java b/app/src/main/java/org/connectbot/HostEditorFragment.java index 6646b4a..56022d7 100644 --- a/app/src/main/java/org/connectbot/HostEditorFragment.java +++ b/app/src/main/java/org/connectbot/HostEditorFragment.java @@ -17,6 +17,9 @@  package org.connectbot; +import java.util.ArrayList; +import java.util.Map; +  import android.content.ContentValues;  import android.content.Context;  import android.content.res.TypedArray; @@ -49,14 +52,22 @@ import org.connectbot.util.HostDatabase;  public class HostEditorFragment extends Fragment { +	private static final String ARG_EXISTING_HOST_ID = "existingHostId";  	private static final String ARG_EXISTING_HOST = "existingHost";  	private static final String ARG_IS_EXPANDED = "isExpanded"; +	private static final String ARG_PUBKEY_NAMES = "pubkeyNames"; +	private static final String ARG_PUBKEY_VALUES = "pubkeyValues";  	private static final String ARG_QUICKCONNECT_STRING = "quickConnectString";  	private static final int MINIMUM_FONT_SIZE = 8;  	// The host being edited.  	private HostBean mHost; + +	// The pubkey lists (names and values). Note that these are declared as ArrayLists rather than +	// Lists because Bundles can only contain ArrayLists, not general Lists. +	private ArrayList<String> mPubkeyNames; +	private ArrayList<String> mPubkeyValues;  	// Whether the host is being created for the first time (as opposed to an existing one being  	// edited). @@ -112,12 +123,16 @@ public class HostEditorFragment extends Fragment {  	private Spinner mDelKeySpinner;  	private Spinner mEncodingSpinner; -	public static HostEditorFragment newInstance(HostBean existingHost) { +	public static HostEditorFragment newInstance( +			HostBean existingHost, ArrayList<String> pubkeyNames, ArrayList<String> pubkeyValues) {  		HostEditorFragment fragment = new HostEditorFragment();  		Bundle args = new Bundle();  		if (existingHost != null) { +			args.putLong(ARG_EXISTING_HOST_ID, existingHost.getId());  			args.putParcelable(ARG_EXISTING_HOST, existingHost.getValues());  		} +		args.putStringArrayList(ARG_PUBKEY_NAMES, pubkeyNames); +		args.putStringArrayList(ARG_PUBKEY_VALUES, pubkeyValues);  		fragment.setArguments(args);  		return fragment;  	} @@ -135,10 +150,14 @@ public class HostEditorFragment extends Fragment {  		mIsCreating = existingHostParcelable == null;  		if (existingHostParcelable != null) {  			mHost = HostBean.fromContentValues((ContentValues) existingHostParcelable); +			mHost.setId(bundle.getLong(ARG_EXISTING_HOST_ID));  		} else {  			mHost = new HostBean();  		} +		mPubkeyNames = bundle.getStringArrayList(ARG_PUBKEY_NAMES); +		mPubkeyValues = bundle.getStringArrayList(ARG_PUBKEY_VALUES); +  		mIsUriEditorExpanded = bundle.getBoolean(ARG_IS_EXPANDED);  	} @@ -154,7 +173,7 @@ public class HostEditorFragment extends Fragment {  		transportSelection.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);  		mTransportSpinner.setAdapter(transportSelection);  		for (int i = 0; i < transportNames.length; i++) { -			if (transportNames.equals(mHost.getProtocol())) { +			if (transportNames[i].equals(mHost.getProtocol())) {  				mTransportSpinner.setSelection(i);  				break;  			} @@ -171,6 +190,7 @@ public class HostEditorFragment extends Fragment {  				mHost.setProtocol(protocol);  				mHost.setPort(TransportFactory.getTransport(protocol).getDefaultPort()); +				handleHostChange();  				mQuickConnectContainer.setHint(  						TransportFactory.getFormatHint(protocol, getActivity())); @@ -208,10 +228,12 @@ public class HostEditorFragment extends Fragment {  		mQuickConnectField.setText(oldQuickConnect == null ? mHost.toString() : oldQuickConnect);  		mQuickConnectField.addTextChangedListener(new TextWatcher() {  			@Override -			public void beforeTextChanged(CharSequence s, int start, int count, int after) {} +			public void beforeTextChanged(CharSequence s, int start, int count, int after) { +			}  			@Override -			public void onTextChanged(CharSequence s, int start, int before, int count) {} +			public void onTextChanged(CharSequence s, int start, int before, int count) { +			}  			@Override  			public void afterTextChanged(Editable s) { @@ -265,8 +287,8 @@ public class HostEditorFragment extends Fragment {  				new HostTextFieldWatcher(HostDatabase.FIELD_HOST_NICKNAME));  		mColorSelector = (Spinner) view.findViewById(R.id.color_selector); -		for (int i = 0; i < mColorValues.getIndexCount(); i++) { -			if (mHost.getColor().equals(mColorValues.getString(i))) { +		for (int i = 0; i < mColorValues.length(); i++) { +			if (mColorValues.getString(i).equals(mHost.getColor())) {  				mColorSelector.setSelection(i);  				break;  			} @@ -275,6 +297,7 @@ public class HostEditorFragment extends Fragment {  			@Override  			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {  				mHost.setColor(mColorValues.getString(position)); +				handleHostChange();  			}  			@Override @@ -289,6 +312,7 @@ public class HostEditorFragment extends Fragment {  			public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {  				int fontSize = MINIMUM_FONT_SIZE + progress;  				mHost.setFontSize(fontSize); +				handleHostChange();  				mFontSizeText.setText(Integer.toString(fontSize));  			} @@ -303,8 +327,30 @@ public class HostEditorFragment extends Fragment {  		mFontSizeSeekBar.setProgress(mHost.getFontSize() - MINIMUM_FONT_SIZE);  		mPubkeySpinner = (Spinner) view.findViewById(R.id.pubkey_spinner); -		// TODO: Set up spinner. This requires passing pubkey data into the fragment from the -		// activity and will be part of an upcoming PR. +		final String[] pubkeyNames = new String[mPubkeyNames.size()]; +		mPubkeyNames.toArray(pubkeyNames); +		ArrayAdapter<String> pubkeySelection = new ArrayAdapter<String>( +				getActivity(), android.R.layout.simple_spinner_item, pubkeyNames); +		pubkeySelection.setDropDownViewResource( +				android.R.layout.simple_spinner_dropdown_item); +		mPubkeySpinner.setAdapter(pubkeySelection); +		for (int i = 0; i < pubkeyNames.length; i++) { +			if (mHost.getPubkeyId() == Integer.parseInt(mPubkeyValues.get(i))) { +				mPubkeySpinner.setSelection(i); +				break; +			} +		} +		mPubkeySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { +			@Override +			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { +				mHost.setPubkeyId(Integer.parseInt(mPubkeyValues.get(position))); +				handleHostChange(); +			} + +			@Override +			public void onNothingSelected(AdapterView<?> parent) { +			} +		});  		mUseSshConfirmationContainer = view.findViewById(R.id.ssh_confirmation_container);  		mUseSshAuthSwitch = (SwitchCompat) view.findViewById(R.id.use_ssh_auth_switch); @@ -323,19 +369,21 @@ public class HostEditorFragment extends Fragment {  				} else {  					mHost.setUseAuthAgent(/* don't use */ mSshAuthValues.getString(0));  				} +				handleHostChange();  			}  		}; -		mUseSshAuthSwitch.setOnCheckedChangeListener(authSwitchListener); -		mSshAuthConfirmationCheckbox.setOnCheckedChangeListener(authSwitchListener);  		if (mHost.getUseAuthAgent() == null ||  				mHost.getUseAuthAgent().equals(mSshAuthValues.getString(0))) {  			mUseSshAuthSwitch.setChecked(false);  			mSshAuthConfirmationCheckbox.setChecked(false);  		} else {  			mUseSshAuthSwitch.setChecked(true); +			mUseSshConfirmationContainer.setVisibility(View.VISIBLE);  			mSshAuthConfirmationCheckbox.setChecked(  					mHost.getUseAuthAgent().equals(mSshAuthValues.getString(1)));  		} +		mUseSshAuthSwitch.setOnCheckedChangeListener(authSwitchListener); +		mSshAuthConfirmationCheckbox.setOnCheckedChangeListener(authSwitchListener);  		mCompressionSwitch = (SwitchCompat) view.findViewById(R.id.compression_switch);  		mCompressionSwitch.setChecked(mHost.getCompression()); @@ -363,7 +411,7 @@ public class HostEditorFragment extends Fragment {  				new HostTextFieldWatcher(HostDatabase.FIELD_HOST_POSTLOGIN));  		mDelKeySpinner = (Spinner) view.findViewById(R.id.del_key_spinner); -		for (int i = 0; i < mDelKeyValues.getIndexCount(); i++) { +		for (int i = 0; i < mDelKeyValues.length(); i++) {  			if (mHost.getDelKey().equals(mDelKeyValues.getString(i))) {  				mDelKeySpinner.setSelection(i);  				break; @@ -373,6 +421,7 @@ public class HostEditorFragment extends Fragment {  			@Override  			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {  				mHost.setDelKey(mDelKeyValues.getString(position)); +				handleHostChange();  			}  			@Override @@ -381,8 +430,8 @@ public class HostEditorFragment extends Fragment {  		});  		mEncodingSpinner = (Spinner) view.findViewById(R.id.encoding_spinner); -		// TODO: Set up spinner. This requires passing pubkey data into the fragment from the -		// activity and will be part of an upcoming PR. +		// The spinner is initialized in setCharsetData() because Charset data is not always +		// available when this fragment is created.  		setUriPartsContainerExpanded(mIsUriEditorExpanded); @@ -418,10 +467,48 @@ public class HostEditorFragment extends Fragment {  	public void onSaveInstanceState(Bundle savedInstanceState) {  		super.onSaveInstanceState(savedInstanceState); +		savedInstanceState.putLong(ARG_EXISTING_HOST_ID, mHost.getId());  		savedInstanceState.putParcelable(ARG_EXISTING_HOST, mHost.getValues());  		savedInstanceState.putBoolean(ARG_IS_EXPANDED, mIsUriEditorExpanded);  		savedInstanceState.putString(  				ARG_QUICKCONNECT_STRING, mQuickConnectField.getText().toString()); +		savedInstanceState.putStringArrayList(ARG_PUBKEY_NAMES, mPubkeyNames); +		savedInstanceState.putStringArrayList(ARG_PUBKEY_VALUES, mPubkeyValues); +	} + +	/** +	 * Sets the Charset encoding data for the editor. +	 * @param data A map from Charset display name to Charset value (i.e., unique ID for the +	 *     Charset). +	 */ +	public void setCharsetData(final Map<String, String> data) { +		if (mEncodingSpinner != null) { +			final String[] encodingNames = new String[data.keySet().size()]; +			data.keySet().toArray(encodingNames); +			ArrayAdapter<String> encodingSelection = new ArrayAdapter<String>( +					getActivity(), android.R.layout.simple_spinner_item, encodingNames); +			encodingSelection.setDropDownViewResource( +					android.R.layout.simple_spinner_dropdown_item); +			mEncodingSpinner.setAdapter(encodingSelection); +			for (int i = 0; i < encodingNames.length; i++) { +				if (mHost.getEncoding() != null && +						mHost.getEncoding().equals(data.get(encodingNames[i]))) { +					mEncodingSpinner.setSelection(i); +					break; +				} +			} +			mEncodingSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { +				@Override +				public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { +					mHost.setEncoding(data.get(encodingNames[position])); +					handleHostChange(); +				} + +				@Override +				public void onNothingSelected(AdapterView<?> parent) { +				} +			}); +		}  	}  	private void setUriPartsContainerExpanded(boolean expanded) { @@ -463,10 +550,39 @@ public class HostEditorFragment extends Fragment {  		mHost.setHostname(host.getHostname());  		mHost.setNickname(host.getNickname());  		mHost.setPort(host.getPort()); +		handleHostChange(); +	} + +	/** +	 * Handles a change in the host caused by the user adjusting the values of one of the widgets +	 * in this fragment. If the change has resulted in a valid host, the new value is sent back +	 * to the listener; however, if the change ha resulted in an invalid host, the listener is +	 * notified. +	 */ +	private void handleHostChange() { +		String protocol = (String) mTransportSpinner.getSelectedItem(); +		String quickConnectString = mQuickConnectField.getText().toString(); +		if (protocol == null || protocol.equals("") || +				quickConnectString == null || quickConnectString.equals("")) { +			// Invalid protocol and/or string, so don't do anything. +			mListener.onHostInvalidated(); +			return; +		} + +		Uri uri = TransportFactory.getUri(protocol, quickConnectString); +		if (uri == null) { +			// Valid string, but does not accurately describe a URI. +			mListener.onHostInvalidated(); +			return; +		} + +		// Now, the host is confirmed to have a valid URI. +		mListener.onValidHostConfigured(mHost);  	}  	public interface Listener { -		public void onHostUpdated(HostBean host); +		public void onValidHostConfigured(HostBean host); +		public void onHostInvalidated();  	}  	private class HostTextFieldWatcher implements TextWatcher { @@ -515,6 +631,7 @@ public class HostEditorFragment extends Fragment {  					mUriFieldEditInProgress = false;  				}  			} +			handleHostChange();  		}  		private boolean isUriRelatedField(String fieldType) { @@ -545,6 +662,7 @@ public class HostEditorFragment extends Fragment {  			} else {  				throw new RuntimeException("Invalid field type.");  			} +			handleHostChange();  		}  	}  } diff --git a/app/src/main/java/org/connectbot/HostListActivity.java b/app/src/main/java/org/connectbot/HostListActivity.java index 3ad8c55..509ef80 100644 --- a/app/src/main/java/org/connectbot/HostListActivity.java +++ b/app/src/main/java/org/connectbot/HostListActivity.java @@ -223,8 +223,8 @@ public class HostListActivity extends AppCompatListActivity implements OnHostSta  		addHostButton.setOnClickListener(new View.OnClickListener() {  			@Override  			public void onClick(View v) { -				DialogFragment dialog = new AddHostDialogFragment(); -				dialog.show(getSupportFragmentManager(), "AddHostDialogFragment"); +				Intent intent = EditHostActivity.createIntentForNewHost(HostListActivity.this); +				startActivityForResult(intent, REQUEST_EDIT);  			}  			public void onNothingSelected(AdapterView<?> arg0) {} @@ -439,8 +439,8 @@ public class HostListActivity extends AppCompatListActivity implements OnHostSta  			MenuItem edit = menu.add(R.string.list_host_edit);  			edit.setOnMenuItemClickListener(new OnMenuItemClickListener() {  				public boolean onMenuItemClick(MenuItem item) { -					Intent intent = new Intent(HostListActivity.this, HostEditorActivity.class); -					intent.putExtra(Intent.EXTRA_TITLE, host.getId()); +					Intent intent = EditHostActivity.createIntentForExistingHost( +							HostListActivity.this, host.getId());  					HostListActivity.this.startActivityForResult(intent, REQUEST_EDIT);  					return true;  				} diff --git a/app/src/main/java/org/connectbot/bean/HostBean.java b/app/src/main/java/org/connectbot/bean/HostBean.java index d6cf8f4..438713e 100644 --- a/app/src/main/java/org/connectbot/bean/HostBean.java +++ b/app/src/main/java/org/connectbot/bean/HostBean.java @@ -47,7 +47,7 @@ public class HostBean extends AbstractBean {  	private boolean useKeys = true;  	private String useAuthAgent = HostDatabase.AUTHAGENT_NO;  	private String postLogin = null; -	private long pubkeyId = -1; +	private long pubkeyId = HostDatabase.PUBKEYID_ANY;  	private boolean wantSession = true;  	private String delKey = HostDatabase.DELKEY_DEL;  	private int fontSize = DEFAULT_FONT_SIZE; @@ -226,8 +226,8 @@ public class HostBean extends AbstractBean {  		values.put(HostDatabase.FIELD_HOST_FONTSIZE, fontSize);  		values.put(HostDatabase.FIELD_HOST_COMPRESSION, Boolean.toString(compression));  		values.put(HostDatabase.FIELD_HOST_ENCODING, encoding); -		values.put(HostDatabase.FIELD_HOST_STAYCONNECTED, stayConnected); -		values.put(HostDatabase.FIELD_HOST_QUICKDISCONNECT, quickDisconnect); +		values.put(HostDatabase.FIELD_HOST_STAYCONNECTED, Boolean.toString(stayConnected)); +		values.put(HostDatabase.FIELD_HOST_QUICKDISCONNECT, Boolean.toString(quickDisconnect));  		return values;  	} diff --git a/app/src/main/java/org/connectbot/util/HostDatabase.java b/app/src/main/java/org/connectbot/util/HostDatabase.java index 074e081..632e333 100644 --- a/app/src/main/java/org/connectbot/util/HostDatabase.java +++ b/app/src/main/java/org/connectbot/util/HostDatabase.java @@ -200,7 +200,7 @@ public class HostDatabase extends RobustSQLiteOpenHelper implements HostStorage,  				+ FIELD_HOST_WANTSESSION + " TEXT DEFAULT '" + Boolean.toString(true) + "', "  				+ FIELD_HOST_COMPRESSION + " TEXT DEFAULT '" + Boolean.toString(false) + "', "  				+ FIELD_HOST_ENCODING + " TEXT DEFAULT '" + ENCODING_DEFAULT + "', " -				+ FIELD_HOST_STAYCONNECTED + " TEXT, " +				+ FIELD_HOST_STAYCONNECTED + " TEXT DEFAULT '" + Boolean.toString(false) + "', "  				+ FIELD_HOST_QUICKDISCONNECT + " TEXT DEFAULT '" + Boolean.toString(false) + "')");  		db.execSQL("CREATE TABLE " + TABLE_PORTFORWARDS | 
