diff --git a/xwords4/android/XWords4/jni/utilwrapper.c b/xwords4/android/XWords4/jni/utilwrapper.c
index 2e66f2e1e..73139e5a9 100644
--- a/xwords4/android/XWords4/jni/utilwrapper.c
+++ b/xwords4/android/XWords4/jni/utilwrapper.c
@@ -146,7 +146,29 @@ static XP_Bool
and_util_askPassword( XW_UtilCtxt* uc, const XP_UCHAR* name,
XP_UCHAR* buf, XP_U16* len )
{
- return XP_FALSE;;
+ XP_Bool result = false;
+ UTIL_CBK_HEADER("askPassword", "(Ljava/lang/String;)Ljava/lang/String;" );
+
+ jstring jname = (*env)->NewStringUTF( env, name );
+ jstring jstr = (*env)->CallObjectMethod( env, util->jutil, mid,
+ jname );
+ (*env)->DeleteLocalRef( env, jname );
+
+ if ( NULL != jstr ) { /* null means user cancelled */
+ jsize jsiz = (*env)->GetStringUTFLength( env, jstr );
+ if ( jsiz < *len ) {
+ const char* chars = (*env)->GetStringUTFChars( env, jstr, NULL );
+ XP_MEMCPY( buf, chars, jsiz );
+ (*env)->ReleaseStringUTFChars( env, jstr, chars );
+ buf[jsiz] = '\0';
+ *len = jsiz;
+ result = XP_TRUE;
+ }
+ (*env)->DeleteLocalRef( env, jstr );
+ }
+
+ UTIL_CBK_TAIL();
+ return result;
}
diff --git a/xwords4/android/XWords4/res/layout/passwd_view.xml b/xwords4/android/XWords4/res/layout/passwd_view.xml
new file mode 100644
index 000000000..0a37a1325
--- /dev/null
+++ b/xwords4/android/XWords4/res/layout/passwd_view.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/xwords4/android/XWords4/res/values/strings.xml b/xwords4/android/XWords4/res/values/strings.xml
index 8a9420204..5f3f1f391 100644
--- a/xwords4/android/XWords4/res/values/strings.xml
+++ b/xwords4/android/XWords4/res/values/strings.xml
@@ -268,6 +268,8 @@
Download
Unable to open game because dictionary %s
not found.
+
+ Password for \"%s\":
key_color_tiles
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java
index 58e877ed1..96d951bc9 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java
@@ -8,6 +8,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuInflater;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.os.Handler;
import android.os.Message;
import android.content.Intent;
@@ -17,6 +18,8 @@ import android.app.Dialog;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.widget.Toast;
+import android.widget.EditText;
+import android.widget.TextView;
import junit.framework.Assert;
import android.content.res.Configuration;
import android.content.pm.ActivityInfo;
@@ -33,6 +36,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
private static final int QUERY_REQUEST_BLK = Utils.DIALOG_LAST + 3;
private static final int PICK_TILE_REQUEST_BLK = Utils.DIALOG_LAST + 4;
private static final int QUERY_ENDGAME = Utils.DIALOG_LAST + 5;
+ private static final int ASK_PASSWORD_BLK = Utils.DIALOG_LAST + 6;
private BoardView m_view;
private int m_jniGamePtr;
@@ -44,7 +48,9 @@ public class BoardActivity extends Activity implements UtilCtxt {
private int m_currentOrient;
private String m_dlgBytes = null;
+ private EditText m_passwdEdit = null;
private int m_dlgTitle;
+ private String m_dlgTitleStr;
private String[] m_texts;
private CommonPrefs m_cp;
private JNIUtils m_jniu;
@@ -132,6 +138,22 @@ public class BoardActivity extends Activity implements UtilCtxt {
dialog = ab.create();
dialog.setOnDismissListener( makeODLforBlocking() );
break;
+
+ case ASK_PASSWORD_BLK:
+ ab = new AlertDialog.Builder( this )
+ .setTitle( m_dlgTitleStr )
+ .setView( m_passwdEdit )
+ .setPositiveButton( R.string.button_ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick( DialogInterface dlg,
+ int whichButton ) {
+ m_resultCode = 1;
+ }
+ });
+ dialog = ab.create();
+ dialog.setOnDismissListener( makeODLforBlocking() );
+ break;
+
case QUERY_ENDGAME:
dialog = new AlertDialog.Builder( this )
.setTitle( R.string.query_title )
@@ -166,10 +188,15 @@ public class BoardActivity extends Activity implements UtilCtxt {
switch( id ) {
case DLG_OKONLY:
dialog.setTitle( m_dlgTitle );
+ // FALLTHRU
case DLG_BADWORDS:
case QUERY_REQUEST_BLK:
((AlertDialog)dialog).setMessage( m_dlgBytes );
break;
+ case ASK_PASSWORD_BLK:
+ m_passwdEdit.setText( "", TextView.BufferType.EDITABLE );
+ dialog.setTitle( m_dlgTitleStr );
+ break;
}
super.onPrepareDialog( id, dialog );
}
@@ -575,6 +602,25 @@ public class BoardActivity extends Activity implements UtilCtxt {
return m_resultCode;
}
+ public String askPassword( String name )
+ {
+ String fmt = getString( R.string.msg_ask_password );
+ m_dlgTitleStr = String.format( fmt, name );
+ m_resultCode = 0;
+
+ if ( null == m_passwdEdit ) {
+ LayoutInflater factory = LayoutInflater.from( this );
+ m_passwdEdit = (EditText)factory.inflate( R.layout.passwd_view, null );
+ }
+ waitBlockingDialog( ASK_PASSWORD_BLK );
+
+ String result = null; // means cancelled
+ if ( 0 != m_resultCode ) {
+ result = m_passwdEdit.getText().toString();
+ }
+ return result;
+ }
+
public boolean engineProgressCallback()
{
return ! m_jniThread.busy();
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java
index df07e331a..72b269f6d 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameConfig.java
@@ -225,6 +225,7 @@ public class GameConfig extends Activity implements View.OnClickListener {
LocalPlayer lp = m_gi.players[m_whichPlayer];
Utils.setText( m_curDialog, R.id.player_name_edit, lp.name );
+ Utils.setText( m_curDialog, R.id.password_edit, lp.password );
CheckBox check = (CheckBox)
m_curDialog.findViewById( R.id.remote_check );
@@ -301,9 +302,8 @@ public class GameConfig extends Activity implements View.OnClickListener {
private void getPlayerSettings()
{
LocalPlayer lp = m_gi.players[m_whichPlayer];
- EditText player = (EditText)
- m_curDialog.findViewById( R.id.player_name_edit );
- lp.name = player.getText().toString();
+ lp.name = Utils.getText( m_curDialog, R.id.player_name_edit );
+ lp.password = Utils.getText( m_curDialog, R.id.password_edit );
lp.isRobot = Utils.getChecked( m_curDialog, R.id.robot_check );
lp.isLocal = !Utils.getChecked( m_curDialog, R.id.remote_check );
diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java
index 1d80cc8de..5c288fde8 100644
--- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java
+++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java
@@ -12,6 +12,9 @@ public interface UtilCtxt {
int getSquareBonus( int col, int row );
int userPickTile( /* PickInfo* pi, add once tile-picking is enabled */
int playerNum, String[] texts );
+
+ String askPassword( String name );
+
boolean engineProgressCallback();
// Values for why; should be enums