Open keyboard on passphrase dialog, this should now work on all Android versions... hopefully

This commit is contained in:
Dominik Schürmann 2014-07-27 20:42:39 +02:00
parent 97e8faa1dd
commit 57d9c7a013
4 changed files with 109 additions and 44 deletions

View File

@ -53,10 +53,10 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" /> <uses-permission android:name="android.permission.READ_PROFILE" />
@ -84,12 +84,11 @@
android:name=".ui.FirstTimeActivity" android:name=".ui.FirstTimeActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/app_name" android:label="@string/app_name"
android:windowSoftInputMode="stateHidden" /> android:windowSoftInputMode="stateAlwaysHidden" />
<activity <activity
android:name=".ui.CreateKeyActivity" android:name=".ui.CreateKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_create_key" android:label="@string/title_create_key">
android:windowSoftInputMode="stateHidden">
<meta-data <meta-data
android:name="android.support.PARENT_ACTIVITY" android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.KeyListActivity" /> android:value=".ui.KeyListActivity" />
@ -102,8 +101,7 @@
<activity <activity
android:name=".ui.EditKeyActivity" android:name=".ui.EditKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_edit_key" android:label="@string/title_edit_key" />
android:windowSoftInputMode="stateHidden" />
<activity <activity
android:name=".ui.ViewKeyActivity" android:name=".ui.ViewKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
@ -473,24 +471,24 @@
<service android:name=".service.DummyAccountService"> <service android:name=".service.DummyAccountService">
<intent-filter> <intent-filter>
<action android:name="android.accounts.AccountAuthenticator"/> <action android:name="android.accounts.AccountAuthenticator" />
</intent-filter> </intent-filter>
<meta-data <meta-data
android:name="android.accounts.AccountAuthenticator" android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/account_desc"/> android:resource="@xml/account_desc" />
</service> </service>
<service android:name=".service.ContactSyncAdapterService"> <service android:name=".service.ContactSyncAdapterService">
<intent-filter> <intent-filter>
<action android:name="android.content.SyncAdapter"/> <action android:name="android.content.SyncAdapter" />
</intent-filter> </intent-filter>
<meta-data <meta-data
android:name="android.content.SyncAdapter" android:name="android.content.SyncAdapter"
android:resource="@xml/sync_adapter_desc"/> android:resource="@xml/sync_adapter_desc" />
<meta-data <meta-data
android:name="android.provider.CONTACTS_STRUCTURE" android:name="android.provider.CONTACTS_STRUCTURE"
android:resource="@xml/custom_pgp_contacts_structure"/> android:resource="@xml/custom_pgp_contacts_structure" />
</service> </service>
</application> </application>

View File

@ -33,8 +33,10 @@ import android.support.v4.app.FragmentActivity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
@ -62,7 +64,6 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
private Messenger mMessenger; private Messenger mMessenger;
private EditText mPassphraseEditText; private EditText mPassphraseEditText;
private boolean mCanKB;
/** /**
* Shows passphrase dialog to cache a new passphrase the user enters for using it later for * Shows passphrase dialog to cache a new passphrase the user enters for using it later for
@ -105,7 +106,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
if (!new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase()) { if (!new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase()) {
throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); throw new PgpGeneralException("No passphrase! No passphrase dialog needed!");
} }
} catch(ProviderHelper.NotFoundException e) { } catch (ProviderHelper.NotFoundException e) {
throw new PgpGeneralException("Error: Key not found!", e); throw new PgpGeneralException("Error: Key not found!", e);
} }
} }
@ -165,7 +166,6 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
} }
}); });
alert.setCancelable(false); alert.setCancelable(false);
mCanKB = false;
return alert.create(); return alert.create();
} }
@ -190,7 +190,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
// Early breakout if we are dealing with a symmetric key // Early breakout if we are dealing with a symmetric key
if (secretRing == null) { if (secretRing == null) {
PassphraseCacheService.addCachedPassphrase(activity, Constants.key.symmetric, PassphraseCacheService.addCachedPassphrase(activity, Constants.key.symmetric,
passphrase, getString(R.string.passp_cache_notif_pwd)); passphrase, getString(R.string.passp_cache_notif_pwd));
// also return passphrase back to activity // also return passphrase back to activity
Bundle data = new Bundle(); Bundle data = new Bundle();
data.putString(MESSAGE_DATA_PASSPHRASE, passphrase); data.putString(MESSAGE_DATA_PASSPHRASE, passphrase);
@ -200,7 +200,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
WrappedSecretKey unlockedSecretKey = null; WrappedSecretKey unlockedSecretKey = null;
for(WrappedSecretKey clickSecretKey : secretRing.secretKeyIterator()) { for (WrappedSecretKey clickSecretKey : secretRing.secretKeyIterator()) {
try { try {
boolean unlocked = clickSecretKey.unlock(passphrase); boolean unlocked = clickSecretKey.unlock(passphrase);
if (unlocked) { if (unlocked) {
@ -232,9 +232,9 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
try { try {
PassphraseCacheService.addCachedPassphrase(activity, masterKeyId, passphrase, PassphraseCacheService.addCachedPassphrase(activity, masterKeyId, passphrase,
secretRing.getPrimaryUserIdWithFallback()); secretRing.getPrimaryUserIdWithFallback());
} catch(PgpGeneralException e) { } catch (PgpGeneralException e) {
Log.e(Constants.TAG, "adding of a passhrase failed", e); Log.e(Constants.TAG, "adding of a passphrase failed", e);
} }
if (unlockedSecretKey.getKeyId() != masterKeyId) { if (unlockedSecretKey.getKeyId() != masterKeyId) {
@ -258,22 +258,32 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
} }
}); });
mCanKB = true; // Hack to open keyboard.
// This is the only method that I found to work across all Android versions
// http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
// Notes: * onCreateView can't be used because we want to add buttons to the dialog
// * opening in onActivityCreated does not work on Android 4.4
mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
mPassphraseEditText.post(new Runnable() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
}
});
}
});
mPassphraseEditText.requestFocus();
mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
mPassphraseEditText.setOnEditorActionListener(this);
return alert.show(); return alert.show();
} }
@Override
public void onActivityCreated(Bundle arg0) {
super.onActivityCreated(arg0);
if (mCanKB) {
// request focus and open soft keyboard
mPassphraseEditText.requestFocus();
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
mPassphraseEditText.setOnEditorActionListener(this);
}
}
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
super.onCancel(dialog); super.onCancel(dialog);
@ -282,6 +292,27 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
sendMessageToHandler(MESSAGE_CANCEL); sendMessageToHandler(MESSAGE_CANCEL);
} }
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
Log.d(Constants.TAG, "onDismiss");
// hide keyboard on dismiss
hideKeyboard();
}
private void hideKeyboard() {
InputMethodManager inputManager = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
//check if no view has focus:
View v = getActivity().getCurrentFocus();
if (v == null)
return;
inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
/** /**
* Associate the "done" button on the soft keyboard with the okay button in the view * Associate the "done" button on the soft keyboard with the okay button in the view
*/ */

View File

@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui.dialog;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message; import android.os.Message;
@ -32,6 +33,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
@ -164,18 +166,50 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
} }
}); });
// Hack to open keyboard.
// This is the only method that I found to work across all Android versions
// http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
// Notes: * onCreateView can't be used because we want to add buttons to the dialog
// * opening in onActivityCreated does not work on Android 4.4
mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
mPassphraseEditText.post(new Runnable() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
}
});
}
});
mPassphraseEditText.requestFocus();
mPassphraseAgainEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
mPassphraseAgainEditText.setOnEditorActionListener(this);
return alert.show(); return alert.show();
} }
@Override @Override
public void onActivityCreated(Bundle arg0) { public void onDismiss(DialogInterface dialog) {
super.onActivityCreated(arg0); super.onDismiss(dialog);
// request focus and open soft keyboard // hide keyboard on dismiss
mPassphraseEditText.requestFocus(); hideKeyboard();
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE); }
mPassphraseAgainEditText.setOnEditorActionListener(this); private void hideKeyboard() {
InputMethodManager inputManager = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
//check if no view has focus:
View v = getActivity().getCurrentFocus();
if (v == null)
return;
inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
} }
/** /**

View File

@ -22,6 +22,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:imeOptions="actionNext"
android:inputType="textPersonName" android:inputType="textPersonName"
android:hint="@string/label_name" android:hint="@string/label_name"
android:ems="10" android:ems="10"
@ -32,6 +33,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:imeOptions="actionNext"
android:hint="@string/label_email" android:hint="@string/label_email"
android:ems="10" android:ems="10"
android:inputType="textEmailAddress" /> android:inputType="textEmailAddress" />