Get comms info (host name, etc.) from user and pass it through to the

send proc.  Along the way, write jni code to instantiate a new object
including setting enums.  *Now* I'm ready for networking....
This commit is contained in:
eehouse 2010-01-30 20:06:06 +00:00
parent bb90dce2c4
commit 49402ed218
17 changed files with 536 additions and 153 deletions

View file

@ -15,6 +15,8 @@ local_DEBUG = -DMEM_DEBUG -DDEBUG -DENABLE_LOGGING
local_DEFINES += \
$(local_DEBUG) \
-DXWFEATURE_RELAY \
-DRELAY_NAME_DEFAULT=\"eehouse.org\" \
-DRELAY_PORT_DEFAULT=10999 \
-DXWFEATURE_TURNCHANGENOTIFY \
-DXWFEATURE_SEARCHLIMIT \
-DKEYBOARD_NAV \

View file

@ -54,30 +54,27 @@ and_htons( XP_U16 ss )
error error error
#endif
bool
getInt( JNIEnv* env, jobject obj, const char* name, int* result )
int
getInt( JNIEnv* env, jobject obj, const char* name )
{
bool success = false;
jclass cls = (*env)->GetObjectClass( env, obj );
XP_ASSERT( !!cls );
jfieldID fid = (*env)->GetFieldID( env, cls, name, "I");
XP_ASSERT( !!fid );
*result = (*env)->GetIntField( env, obj, fid );
success = true;
int result = (*env)->GetIntField( env, obj, fid );
(*env)->DeleteLocalRef( env, cls );
return success;
return result;
}
bool
void
setInt( JNIEnv* env, jobject obj, const char* name, int value )
{
bool success = false;
jclass cls = (*env)->GetObjectClass( env, obj );
XP_ASSERT( !!cls );
jfieldID fid = (*env)->GetFieldID( env, cls, name, "I");
XP_ASSERT( !!fid );
(*env)->SetIntField( env, obj, fid, value );
success = true;
(*env)->DeleteLocalRef( env, cls );
return success;
}
bool
@ -153,20 +150,16 @@ getObject( JNIEnv* env, jobject obj, const char* name, const char* sig,
/* return false on failure, e.g. exception raised */
bool
getBool( JNIEnv* env, jobject obj, const char* name, XP_Bool* result )
getBool( JNIEnv* env, jobject obj, const char* name )
{
bool success = false;
bool result;
jclass cls = (*env)->GetObjectClass( env, obj );
XP_ASSERT( !!cls );
jfieldID fid = (*env)->GetFieldID( env, cls, name, "Z");
XP_ASSERT( !!fid );
if ( 0 != fid ) {
*result = (*env)->GetBooleanField( env, obj, fid );
success = true;
}
result = (*env)->GetBooleanField( env, obj, fid );
(*env)->DeleteLocalRef( env, cls );
XP_ASSERT( success );
return success;
return result;
}
jintArray
@ -288,3 +281,110 @@ makeBitmapsArray( JNIEnv* env, const XP_Bitmaps* bitmaps )
return result;
}
void
setJAddrRec( JNIEnv* env, jobject jaddr, const CommsAddrRec* addr )
{
LOG_FUNC();
setInt( env, jaddr, "ip_relay_port", addr->u.ip_relay.port );
setString( env, jaddr, "ip_relay_hostName", addr->u.ip_relay.hostName );
setString( env, jaddr, "ip_relay_invite", addr->u.ip_relay.invite );
intToJenumField( env, jaddr, addr->conType, "conType",
"org/eehouse/android/xw4/jni/CommsAddrRec$CommsConnType" );
/* Later switch off of it... */
XP_ASSERT( addr->conType == COMMS_CONN_RELAY );
LOG_RETURN_VOID();
}
void
getJAddrRec( JNIEnv* env, CommsAddrRec* addr, jobject jaddr )
{
addr->conType = jenumFieldToInt( env, jaddr, "conType",
"org/eehouse/android/xw4/jni/"
"CommsAddrRec$CommsConnType" );
/* Later switch off of it... */
XP_ASSERT( addr->conType == COMMS_CONN_RELAY );
addr->u.ip_relay.port = getInt( env, jaddr, "ip_relay_port" );
XP_UCHAR buf[256]; /* in case needs whole path */
getString( env, jaddr, "ip_relay_hostName", addr->u.ip_relay.hostName,
VSIZE(addr->u.ip_relay.hostName) );
getString( env, jaddr, "ip_relay_invite", addr->u.ip_relay.invite,
VSIZE(addr->u.ip_relay.invite) );
}
jint
jenumFieldToInt( JNIEnv* env, jobject j_gi, const char* field,
const char* fieldSig )
{
XP_LOGF( "IN %s(%s)", __func__, fieldSig );
jclass clazz = (*env)->GetObjectClass( env, j_gi );
XP_ASSERT( !!clazz );
char sig[128];
snprintf( sig, sizeof(sig), "L%s;", fieldSig );
jfieldID fid = (*env)->GetFieldID( env, clazz, field, sig );
XP_ASSERT( !!fid );
jobject jenum = (*env)->GetObjectField( env, j_gi, fid );
XP_ASSERT( !!jenum );
jmethodID mid = getMethodID( env, jenum, "ordinal", "()I" );
jint result = (*env)->CallIntMethod( env, jenum, mid );
(*env)->DeleteLocalRef( env, clazz );
(*env)->DeleteLocalRef( env, jenum );
LOG_RETURNF( "%d", result );
return result;
}
void
intToJenumField( JNIEnv* env, jobject jobj, int val, const char* field,
const char* fieldSig )
{
XP_LOGF( "IN %s(%d,%s,%s)", __func__, val, field, fieldSig );
jclass clazz = (*env)->GetObjectClass( env, jobj );
XP_ASSERT( !!clazz );
char buf[128];
snprintf( buf, sizeof(buf), "L%s;", fieldSig );
jfieldID fid = (*env)->GetFieldID( env, clazz, field, buf );
XP_ASSERT( !!fid ); /* failed */
(*env)->DeleteLocalRef( env, clazz );
jobject jenum = (*env)->GetObjectField( env, jobj, fid );
if ( !jenum ) { /* won't exist in new object */
XP_LOGF( "%s: creating new object...", __func__ );
clazz = (*env)->FindClass( env, fieldSig );
XP_ASSERT( !!clazz );
jmethodID mid = getMethodID( env, clazz, "<init>", "()V" );
XP_ASSERT( !!mid );
jenum = (*env)->NewObject( env, clazz, mid );
XP_ASSERT( !!jenum );
(*env)->SetObjectField( env, jobj, fid, jenum );
} else {
clazz = (*env)->GetObjectClass( env, jenum );
}
XP_ASSERT( !!clazz );
snprintf( buf, sizeof(buf), "()[L%s;", fieldSig );
jmethodID mid = (*env)->GetStaticMethodID( env, clazz, "values", buf );
XP_ASSERT( !!mid );
jobject jvalues = (*env)->CallStaticObjectMethod( env, clazz, mid );
XP_ASSERT( !!jvalues );
XP_ASSERT( val < (*env)->GetArrayLength( env, jvalues ) );
/* get the value we want */
jobject jval = (*env)->GetObjectArrayElement( env, jvalues, val );
XP_ASSERT( !!jval );
(*env)->SetObjectField( env, jobj, fid, jval );
(*env)->DeleteLocalRef( env, jvalues );
(*env)->DeleteLocalRef( env, jval );
(*env)->DeleteLocalRef( env, clazz );
LOG_RETURN_VOID();
} /* intToJenumField */

View file

@ -6,6 +6,7 @@
#include <jni.h>
#include "comtypes.h"
#include "comms.h"
#include "mempool.h"
#include "dictnry.h"
@ -14,9 +15,9 @@ XP_U16 and_ntohs(XP_U16 l);
XP_U32 and_htonl(XP_U32 l);
XP_U16 and_htons(XP_U16 l);
bool getInt( JNIEnv* env, jobject obj, const char* name, int* result );
bool setInt( JNIEnv* env, jobject obj, const char* name, int value );
bool getBool( JNIEnv* env, jobject obj, const char* name, XP_Bool* result );
int getInt( JNIEnv* env, jobject obj, const char* name );
void setInt( JNIEnv* env, jobject obj, const char* name, int value );
bool getBool( JNIEnv* env, jobject obj, const char* name );
bool setBool( JNIEnv* env, jobject obj, const char* name, bool value );
bool setString( JNIEnv* env, jobject obj, const char* name, const XP_UCHAR* value );
bool getString( JNIEnv* env, jobject jlp, const char* name, XP_UCHAR* buf,
@ -40,4 +41,10 @@ jobjectArray makeBitmapsArray( JNIEnv* env, const XP_Bitmaps* bitmaps );
jmethodID getMethodID( JNIEnv* env, jobject obj, const char* proc,
const char* sig );
void setJAddrRec( JNIEnv* env, jobject jaddr, const CommsAddrRec* addr );
void getJAddrRec( JNIEnv* env, CommsAddrRec* addr, jobject jaddr );
jint jenumFieldToInt( JNIEnv* env, jobject j_gi, const char* field,
const char* fieldSig );
void intToJenumField( JNIEnv* env, jobject j_gi, int val, const char* field,
const char* fieldSig );
#endif

View file

@ -1,6 +1,6 @@
/* -*-mode: C; compile-command: "cd XWords4; ../scripts/ndkbuild.sh"; -*- */
/* -*-mode: C; compile-command: "../../scripts/ndkbuild.sh"; -*- */
/*
* Copyright 2001-2009 by Eric House (xwords@eehouse.org). All rights
* Copyright 2001-2010 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -69,15 +69,10 @@ makeJRect( AndDraw* draw, int indx, const XP_Rect* rect )
static void
copyJRect( JNIEnv* env, XP_Rect* dest, jobject jrect )
{
int tmp;
getInt( env, jrect, "left", &tmp );
dest->left = tmp;
getInt( env, jrect, "top", &tmp );
dest->top = tmp;
getInt( env, jrect, "right", &tmp );
dest->width = tmp - dest->left;
getInt( env, jrect, "bottom", &tmp );
dest->height = tmp - dest->top;
dest->left = getInt( env, jrect, "left" );
dest->top = getInt( env, jrect, "top" );
dest->width = getInt( env, jrect, "right" ) - dest->left;
dest->height = getInt( env, jrect, "bottom" ) - dest->top;
}
static jobject
@ -98,16 +93,15 @@ makeDSI( AndDraw* draw, int indx, const DrawScoreInfo* dsi )
draw->jCache[indx] = dsiobj;
}
bool success = setInt( env, dsiobj, "playerNum", dsi->playerNum )
&& setInt( env, dsiobj, "totalScore", dsi->totalScore )
&& setInt( env, dsiobj, "nTilesLeft", dsi->nTilesLeft )
&& setInt( env, dsiobj, "flags", dsi->flags )
&& setBool( env, dsiobj, "isTurn", dsi->isTurn )
&& setBool( env, dsiobj, "selected", dsi->selected )
&& setBool( env, dsiobj, "isRemote", dsi->isRemote )
&& setBool( env, dsiobj, "isRobot", dsi->isRobot )
&& setString( env, dsiobj, "name", dsi->name )
;
setInt( env, dsiobj, "playerNum", dsi->playerNum );
setInt( env, dsiobj, "totalScore", dsi->totalScore );
setInt( env, dsiobj, "nTilesLeft", dsi->nTilesLeft );
setInt( env, dsiobj, "flags", dsi->flags );
setBool( env, dsiobj, "isTurn", dsi->isTurn );
setBool( env, dsiobj, "selected", dsi->selected );
setBool( env, dsiobj, "isRemote", dsi->isRemote );
setBool( env, dsiobj, "isRobot", dsi->isRobot );
setString( env, dsiobj, "name", dsi->name );
return dsiobj;
}

View file

@ -28,6 +28,26 @@ typedef struct _AndTransportProcs {
MPSLOT
} AndTransportProcs;
static jobject
makeJAddr( JNIEnv* env, const CommsAddrRec* addr )
{
LOG_FUNC();
jobject jaddr;
jclass clazz
= (*env)->FindClass(env, "org/eehouse/android/xw4/jni/CommsAddrRec");
XP_ASSERT( !!clazz );
jmethodID mid = getMethodID( env, clazz, "<init>", "()V" );
XP_ASSERT( !!mid );
jaddr = (*env)->NewObject( env, clazz, mid );
XP_ASSERT( !!jaddr );
setJAddrRec( env, jaddr, addr );
(*env)->DeleteLocalRef( env, clazz );
LOG_RETURNF( "%p", jaddr );
return jaddr;
}
static XP_S16
and_xport_send( const XP_U8* buf, XP_U16 len, const CommsAddrRec* addr,
@ -40,10 +60,14 @@ and_xport_send( const XP_U8* buf, XP_U16 len, const CommsAddrRec* addr,
jmethodID mid = getMethodID( env, aprocs->j_xport, "transportSend", sig );
jbyteArray jbytes = makeByteArray( env, len, buf );
jobject jaddr = makeJAddr( env, addr );
jint result = (*env)->CallIntMethod( env, aprocs->j_xport, mid,
jbytes, NULL );
jbytes, jaddr );
(*env)->DeleteLocalRef( env, jaddr );
(*env)->DeleteLocalRef( env, jbytes );
LOG_RETURNF( "%d", result );
return result;
}

View file

@ -17,85 +17,20 @@
#include "anddict.h"
#include "andutils.h"
static jint
jenumFieldToInt( JNIEnv* env, jobject j_gi, const char* field,
const char* fieldSig )
{
LOG_FUNC();
jclass clazz = (*env)->GetObjectClass( env, j_gi );
XP_ASSERT( !!clazz );
char sig[128];
snprintf( sig, sizeof(sig), "L%s;", fieldSig );
jfieldID fid = (*env)->GetFieldID( env, clazz, field, sig );
XP_ASSERT( !!fid );
jobject jenum = (*env)->GetObjectField( env, j_gi, fid );
XP_ASSERT( !!jenum );
jmethodID mid = getMethodID( env, jenum, "ordinal", "()I" );
jint result = (*env)->CallIntMethod( env, jenum, mid );
(*env)->DeleteLocalRef( env, clazz );
(*env)->DeleteLocalRef( env, jenum );
LOG_RETURNF( "%d", result );
return result;
}
static void
intToJenumField( JNIEnv* env, jobject j_gi, int val, const char* field,
const char* fieldSig )
{
XP_LOGF( "IN %s(%d)", __func__, val );
jclass clazz = (*env)->GetObjectClass( env, j_gi );
XP_ASSERT( !!clazz );
char buf[128];
snprintf( buf, sizeof(buf), "L%s;", fieldSig );
jfieldID fid = (*env)->GetFieldID( env, clazz, field, buf );
XP_ASSERT( !!fid ); /* failed */
jobject jenum = (*env)->GetObjectField( env, j_gi, fid );
XP_ASSERT( !!jenum );
(*env)->DeleteLocalRef( env, clazz );
clazz = (*env)->GetObjectClass( env, jenum );
XP_ASSERT( !!clazz );
snprintf( buf, sizeof(buf), "()[L%s;", fieldSig );
jmethodID mid = (*env)->GetStaticMethodID( env, clazz, "values", buf );
XP_ASSERT( !!mid );
jobject jvalues = (*env)->CallStaticObjectMethod( env, clazz, mid );
XP_ASSERT( !!jvalues );
XP_ASSERT( val < (*env)->GetArrayLength( env, jvalues ) );
/* get the value we want */
jobject jval = (*env)->GetObjectArrayElement( env, jvalues, val );
XP_ASSERT( !!jval );
(*env)->SetObjectField( env, j_gi, fid, jval );
(*env)->DeleteLocalRef( env, jvalues );
(*env)->DeleteLocalRef( env, jval );
(*env)->DeleteLocalRef( env, clazz );
LOG_RETURN_VOID();
}
static CurGameInfo*
makeGI( MPFORMAL JNIEnv* env, jobject j_gi )
{
CurGameInfo* gi = (CurGameInfo*)XP_CALLOC( mpool, sizeof(*gi) );
int nPlayers, robotSmartness, boardSize;
XP_UCHAR buf[256]; /* in case needs whole path */
bool success = getInt( env, j_gi, "nPlayers", &nPlayers )
&& getInt( env, j_gi, "boardSize", &boardSize )
&& getInt( env, j_gi, "robotSmartness", &robotSmartness )
&& getBool( env, j_gi, "hintsNotAllowed", &gi->hintsNotAllowed )
&& getBool( env, j_gi, "timerEnabled", &gi->timerEnabled )
&& getBool( env, j_gi, "allowPickTiles", &gi->allowPickTiles )
&& getBool( env, j_gi, "allowHintRect", &gi->allowHintRect )
;
XP_ASSERT( success );
gi->nPlayers = getInt( env, j_gi, "nPlayers");
gi->boardSize = getInt( env, j_gi, "boardSize" );
gi->robotSmartness = getInt( env, j_gi, "robotSmartness" );
gi->hintsNotAllowed = getBool( env, j_gi, "hintsNotAllowed" );
gi->timerEnabled = getBool( env, j_gi, "timerEnabled" );
gi->allowPickTiles = getBool( env, j_gi, "allowPickTiles" );
gi->allowHintRect = getBool( env, j_gi, "allowHintRect" );
gi->nPlayers = nPlayers;
gi->robotSmartness = robotSmartness;
gi->boardSize = boardSize;
gi->serverRole =
jenumFieldToInt( env, j_gi, "serverRole",
"org/eehouse/android/xw4/jni/CurGameInfo$DeviceRole");
@ -103,7 +38,7 @@ makeGI( MPFORMAL JNIEnv* env, jobject j_gi )
getString( env, j_gi, "dictName", buf, VSIZE(buf) );
gi->dictName = copyString( mpool, buf );
XP_ASSERT( nPlayers <= MAX_NUM_PLAYERS );
XP_ASSERT( gi->nPlayers <= MAX_NUM_PLAYERS );
jobject jplayers;
if ( getObject( env, j_gi, "players",
@ -116,8 +51,8 @@ makeGI( MPFORMAL JNIEnv* env, jobject j_gi )
jobject jlp = (*env)->GetObjectArrayElement( env, jplayers, ii );
XP_ASSERT( !!jlp );
getBool( env, jlp, "isRobot", &lp->isRobot );
getBool( env, jlp, "isLocal", &lp->isLocal );
lp->isRobot = getBool( env, jlp, "isRobot" );
lp->isLocal = getBool( env, jlp, "isLocal" );
getString( env, jlp, "name", buf, VSIZE(buf) );
lp->name = copyString( mpool, buf );
@ -140,16 +75,14 @@ static void
setJGI( JNIEnv* env, jobject jgi, const CurGameInfo* gi )
{
// set fields
bool success = setInt( env, jgi, "nPlayers", gi->nPlayers )
&& setInt( env, jgi, "boardSize", gi->boardSize )
&& setInt( env, jgi, "robotSmartness", gi->robotSmartness )
&& setBool( env, jgi, "hintsNotAllowed", gi->hintsNotAllowed )
&& setBool( env, jgi, "timerEnabled", gi->timerEnabled )
&& setBool( env, jgi, "allowPickTiles", gi->allowPickTiles )
&& setBool( env, jgi, "allowHintRect", gi->allowHintRect )
&& setString( env, jgi, "dictName", gi->dictName )
;
XP_ASSERT( success );
setInt( env, jgi, "nPlayers", gi->nPlayers );
setInt( env, jgi, "boardSize", gi->boardSize );
setInt( env, jgi, "robotSmartness", gi->robotSmartness );
setBool( env, jgi, "hintsNotAllowed", gi->hintsNotAllowed );
setBool( env, jgi, "timerEnabled", gi->timerEnabled );
setBool( env, jgi, "allowPickTiles", gi->allowPickTiles );
setBool( env, jgi, "allowHintRect", gi->allowHintRect );
setString( env, jgi, "dictName", gi->dictName );
intToJenumField( env, jgi, gi->serverRole, "serverRole",
"org/eehouse/android/xw4/jni/CurGameInfo$DeviceRole" );
@ -186,14 +119,13 @@ destroyGI( MPFORMAL CurGameInfo* gi )
XP_FREE( mpool, gi );
}
static bool
static void
loadCommonPrefs( JNIEnv* env, CommonPrefs* cp, jobject j_cp )
{
bool success = getBool( env, j_cp, "showBoardArrow", &cp->showBoardArrow )
&& getBool( env, j_cp, "showRobotScores", &cp->showRobotScores )
&& getBool( env, j_cp, "hideTileValues", &cp->hideTileValues )
&& getBool( env, j_cp, "skipCommitConfirm", &cp->skipCommitConfirm );
return success;
cp->showBoardArrow = getBool( env, j_cp, "showBoardArrow" );
cp->showRobotScores = getBool( env, j_cp, "showRobotScores" );
cp->hideTileValues = getBool( env, j_cp, "hideTileValues" );
cp->skipCommitConfirm = getBool( env, j_cp, "skipCommitConfirm" );
}
static XWStreamCtxt*
@ -205,7 +137,7 @@ and_empty_stream( MPFORMAL AndGlobals* globals, void* closure )
}
/****************************************************
* These two methods are stateless: no gamePtr
* These three methods are stateless: no gamePtr
****************************************************/
JNIEXPORT jbyteArray JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_gi_1to_1stream
@ -275,6 +207,16 @@ Java_org_eehouse_android_xw4_jni_XwJNI_gi_1from_1stream
LOG_RETURN_VOID();
}
JNIEXPORT void JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1getInitialAddr
( JNIEnv* env, jclass C, jobject jaddr )
{
LOG_FUNC();
CommsAddrRec addr;
comms_getInitialAddr( &addr );
setJAddrRec( env, jaddr, &addr );
}
typedef struct _JNIState {
XWGame game;
JNIEnv* env;
@ -331,7 +273,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeNewGame
globals->dctx = dctx;
globals->xportProcs = makeXportProcs( MPPARM(mpool) &state->env, j_procs );
CommonPrefs cp;
(void)loadCommonPrefs( env, &cp, j_cp );
loadCommonPrefs( env, &cp, j_cp );
XP_LOGF( "calling game_makeNewGame" );
game_makeNewGame( MPPARM(mpool) &state->game, gi, util, dctx, gameID,
@ -399,7 +341,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeFromStream
(*env)->ReleaseByteArrayElements( env, jstream, jelems, 0 );
CommonPrefs cp;
(void)loadCommonPrefs( env, &cp, jcp );
loadCommonPrefs( env, &cp, jcp );
result = game_makeFromStream( MPPARM(mpool) stream, &state->game,
globals->gi, dict,
globals->util, globals->dctx, &cp,
@ -806,3 +748,30 @@ Java_org_eehouse_android_xw4_jni_XwJNI_comms_1start
XWJNI_END();
}
JNIEXPORT void JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1getAddr
(JNIEnv* env, jclass C, jint gamePtr, jobject jaddr )
{
XWJNI_START();
LOG_FUNC();
XP_ASSERT( state->game.comms );
CommsAddrRec addr;
comms_getAddr( state->game.comms, &addr );
setJAddrRec( env, jaddr, &addr );
XWJNI_END();
}
JNIEXPORT void JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1setAddr
( JNIEnv* env, jclass C, jint gamePtr, jobject jaddr )
{
XWJNI_START();
if ( state->game.comms ) {
CommsAddrRec addr;
getJAddrRec( env, &addr, jaddr );
comms_setAddr( state->game.comms, &addr );
} else {
XP_LOGF( "%s: no comms this game" );
}
XWJNI_END();
}

View file

@ -38,6 +38,12 @@
android:drawSelectorOnTop="true"
/>
<Button android:id="@+id/configure_role"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/configure_role"
/>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

View file

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/screen"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<!-- This eventually wants to be a tabbed dialog switching off of the
connType: different tab for SMS, Relay, Bluetooth, etc. -->
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:text="@string/room_label"
android:gravity="left"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<EditText android:id="@+id/room_edit"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:scrollHorizontally="true"
android:autoText="false"
android:capitalize="none"
android:gravity="fill_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<TextView android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:text="@string/hostname_label"
android:gravity="left"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<EditText android:id="@+id/hostname_edit"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:scrollHorizontally="true"
android:autoText="false"
android:capitalize="none"
android:gravity="fill_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<TextView android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:text="@string/port_label"
android:gravity="left"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<EditText android:id="@+id/port_edit"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:scrollHorizontally="true"
android:autoText="false"
android:numeric="decimal"
android:gravity="fill_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
</LinearLayout>
</ScrollView>

View file

@ -153,6 +153,7 @@
<string name="dict_label">Dictionary</string>
<string name="role_label">Role</string>
<string name="configure_role">Configure role</string>
<string name="phonies_label">Phonies</string>
<string name="download_dicts">Download more...</string>
@ -176,4 +177,10 @@
<string name="phonies_warn">Warn</string>
<string name="phonies_disallow">Disallow</string>
<string name="gamel_menu_prefs">Preferences</string>
<string name="room_label">Room</string>
<string name="hostname_label">Hostname</string>
<string name="port_label">Port</string>
<string name="role_edit_title">Connection</string>
</resources>

View file

@ -41,6 +41,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
private BoardView m_view;
private int m_jniGamePtr;
private CurGameInfo m_gi;
CommsTransport m_xport;
private Handler m_handler;
private TimerRunnable[] m_timers;
private String m_path;
@ -136,17 +137,17 @@ public class BoardActivity extends Activity implements UtilCtxt {
} else {
m_jniGamePtr = XwJNI.initJNI();
CommsTransport xport
= ( m_gi.serverRole == DeviceRole.SERVER_STANDALONE )
? null : new CommsTransport();
if ( m_gi.serverRole != DeviceRole.SERVER_STANDALONE ) {
m_xport = new CommsTransport( m_jniGamePtr );
}
if ( null == stream ||
! XwJNI.game_makeFromStream( m_jniGamePtr, stream,
m_gi, dictBytes, this,
m_view, Utils.getCP(),
xport ) ) {
m_xport ) ) {
XwJNI.game_makeNewGame( m_jniGamePtr, m_gi, this, m_view, 0,
Utils.getCP(), xport, dictBytes );
Utils.getCP(), m_xport, dictBytes );
}
m_jniThread = new

View file

@ -1,16 +1,42 @@
/* -*- compile-command: "cd ../../../../../; ant reinstall"; -*- */
package org.eehouse.android.xw4;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import org.eehouse.android.xw4.jni.*;
public class CommsTransport implements TransportProcs {
public class CommsTransport extends Thread implements TransportProcs {
private Selector m_selector;
private SocketChannel m_socketChannel;
private int m_jniGamePtr;
// private CommsAddrRec m_addr;
public int transportSend( byte[] buf, final CommsAddrRec addr )
public CommsTransport( int jniGamePtr )
{
Utils.logf( "CommsTransport::transportSend() called!!!" );
return -1;
m_jniGamePtr = jniGamePtr;
}
@Override
public void run()
{
}
// TransportProcs interface
public int transportSend( byte[] buf, final CommsAddrRec faddr )
{
Utils.logf( "CommsTransport::transportSend" );
CommsAddrRec addr = faddr;
if ( null == addr ) {
addr = new CommsAddrRec();
XwJNI.comms_getAddr( m_jniGamePtr, addr );
}
Utils.logf( "CommsTransport::transportSend(" + addr.ip_relay_hostName +
") called!!!" );
return buf.length;
}
public void relayStatus( int newState )

View file

@ -74,8 +74,10 @@ import org.eehouse.android.xw4.jni.*;
public class GameConfig extends Activity implements View.OnClickListener {
private static final int PLAYER_EDIT = 1;
private static final int ROLE_EDIT = 2;
private Button m_addPlayerButton;
private Button m_configureButton;
private String m_path;
private CurGameInfo m_gi;
private int m_whichPlayer;
@ -86,18 +88,21 @@ public class GameConfig extends Activity implements View.OnClickListener {
private String[] m_dicts;
private int m_browsePosition;
private LinearLayout m_playerLayout;
private CommsAddrRec m_car;
@Override
protected Dialog onCreateDialog( int id )
{
LayoutInflater factory;
DialogInterface.OnClickListener dlpos;
switch (id) {
case PLAYER_EDIT:
LayoutInflater factory = LayoutInflater.from(this);
factory = LayoutInflater.from(this);
final View playerEditView
= factory.inflate( R.layout.player_edit, null );
DialogInterface.OnClickListener dlpos =
new DialogInterface.OnClickListener() {
dlpos = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog,
int whichButton ) {
getPlayerSettings();
@ -111,6 +116,24 @@ public class GameConfig extends Activity implements View.OnClickListener {
.setView(playerEditView)
.setPositiveButton(R.string.button_save, dlpos )
.create();
case ROLE_EDIT:
factory = LayoutInflater.from(this);
final View roleEditView
= factory.inflate( R.layout.role_edit, null );
dlpos = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog,
int whichButton ) {
getRoleSettings();
}
};
return new AlertDialog.Builder( this )
// .setIcon(R.drawable.alert_dialog_icon)
.setTitle(R.string.role_edit_title)
.setView(roleEditView)
.setPositiveButton(R.string.button_save, dlpos )
.create();
}
return null;
}
@ -119,7 +142,14 @@ public class GameConfig extends Activity implements View.OnClickListener {
protected void onPrepareDialog( int id, Dialog dialog )
{
m_curDialog = dialog;
setPlayerSettings();
switch ( id ) {
case PLAYER_EDIT:
setPlayerSettings();
break;
case ROLE_EDIT:
setRoleSettings();
break;
}
super.onPrepareDialog( id, dialog );
}
@ -134,6 +164,25 @@ public class GameConfig extends Activity implements View.OnClickListener {
Utils.setChecked( m_curDialog, R.id.remote_check, ! lp.isLocal );
}
private void setRoleSettings()
{
if ( null == m_car ) {
m_car = new CommsAddrRec( CommsAddrRec.get() );
}
Utils.setText( m_curDialog, R.id.room_edit, m_car.ip_relay_invite );
Utils.setText( m_curDialog, R.id.hostname_edit,
m_car.ip_relay_hostName );
Utils.setInt( m_curDialog, R.id.port_edit, m_car.ip_relay_port );
}
private void getRoleSettings()
{
m_car.ip_relay_invite = Utils.getText( m_curDialog, R.id.room_edit );
m_car.ip_relay_hostName = Utils.getText( m_curDialog,
R.id.hostname_edit );
m_car.ip_relay_port = Utils.getInt( m_curDialog, R.id.port_edit );
}
private void getPlayerSettings()
{
LocalPlayer lp = m_gi.players[m_whichPlayer];
@ -166,6 +215,8 @@ public class GameConfig extends Activity implements View.OnClickListener {
m_addPlayerButton = (Button)findViewById(R.id.add_player);
m_addPlayerButton.setOnClickListener( this );
m_configureButton = (Button)findViewById(R.id.configure_role);
m_configureButton.setOnClickListener( this );
m_playerLayout = (LinearLayout)findViewById( R.id.player_list );
loadPlayers();
@ -306,6 +357,10 @@ public class GameConfig extends Activity implements View.OnClickListener {
Utils.saveGame( this, bytes, m_path );
}
if ( null != m_car ) {
CommsAddrRec.set( m_car );
}
finish();
break;
default:
@ -324,6 +379,8 @@ public class GameConfig extends Activity implements View.OnClickListener {
m_whichPlayer = curIndex;
showDialog( PLAYER_EDIT );
}
} else if ( m_configureButton == view ) {
showDialog( ROLE_EDIT );
} else {
Utils.logf( "unknown v: " + view.toString() );
}

View file

@ -17,6 +17,8 @@ import java.io.InputStream;
import android.widget.CheckBox;
import android.app.Activity;
import android.app.Dialog;
import android.widget.EditText;
import android.widget.TextView;
import org.eehouse.android.xw4.jni.*;
@ -202,6 +204,20 @@ public class Utils {
cbx.setChecked( value );
}
public static void setText( Dialog dialog, int id, String value )
{
EditText editText = (EditText)dialog.findViewById( id );
if ( null != editText ) {
editText.setText( value, TextView.BufferType.EDITABLE );
}
}
public static void setInt( Dialog dialog, int id, int value )
{
String str = Integer.toString(value);
setText( dialog, id, str );
}
public static boolean getChecked( Activity activity, int id )
{
CheckBox cbx = (CheckBox)activity.findViewById( id );
@ -214,6 +230,18 @@ public class Utils {
return cbx.isChecked();
}
public static String getText( Dialog dialog, int id )
{
EditText editText = (EditText)dialog.findViewById( id );
return editText.getText().toString();
}
public static int getInt( Dialog dialog, int id )
{
String str = getText( dialog, id );
return Integer.parseInt( str );
}
public static CommonPrefs getCP()
{
if ( null == m_cp ) {

View file

@ -1,5 +1,70 @@
/* -*- compile-command: "cd ../../../../../../; ant reinstall"; -*- */
package org.eehouse.android.xw4.jni;
import java.net.InetAddress;
import org.eehouse.android.xw4.Utils;
public class CommsAddrRec {
public enum CommsConnType { COMMS_CONN_NONE,
COMMS_CONN_IR,
COMMS_CONN_IP_DIRECT,
COMMS_CONN_RELAY,
COMMS_CONN_BT,
COMMS_CONN_SMS,
};
// The C equivalent of this struct uses a union for the various
// data sets below. So don't assume that any fields will be valid
// except those for the current conType.
public CommsConnType conType;
// relay case
public String ip_relay_invite;
public String ip_relay_hostName;
public InetAddress ip_relay_ipAddr; // a cache, maybe unused in java
public int ip_relay_port;
// sms case
public String sms_phone;
public int sms_port; // NBS port, if they still use those
public CommsAddrRec() {
Utils.logf( "CommsAddrRec() called " );
conType = CommsConnType.COMMS_CONN_RELAY;
ip_relay_invite = "Room 1";
ip_relay_hostName = "eehouse.org";
ip_relay_port = 10999;
}
public CommsAddrRec( CommsAddrRec src ) {
this.copyFrom(src );
}
private void copyFrom( CommsAddrRec src )
{
conType = src.conType;
ip_relay_invite = src.ip_relay_invite;
ip_relay_hostName = src.ip_relay_hostName;
ip_relay_port = src.ip_relay_port;
}
private static CommsAddrRec s_car;
public static final CommsAddrRec get()
{
if ( null == s_car ) {
s_car = new CommsAddrRec();
}
return s_car;
}
public static void set( final CommsAddrRec car )
{
if ( null == s_car ) {
s_car = new CommsAddrRec( car );
} else {
s_car.copyFrom( car );
}
}
}

View file

@ -174,6 +174,7 @@ public class JNIThread extends Thread {
break;
case CMD_START:
XwJNI.comms_setAddr( m_jniGamePtr, CommsAddrRec.get() );
XwJNI.comms_start( m_jniGamePtr );
if ( m_gi.serverRole == DeviceRole.SERVER_ISCLIENT ) {
XwJNI.server_initClientConnection( m_jniGamePtr );

View file

@ -21,6 +21,7 @@ public class XwJNI {
// Stateless methods
public static native byte[] gi_to_stream( CurGameInfo gi );
public static native void gi_from_stream( CurGameInfo gi, byte[] stream );
public static native void comms_getInitialAddr( CommsAddrRec addr );
// Game methods
public static native int initJNI();
@ -95,5 +96,6 @@ public class XwJNI {
// Comms
public static native void comms_start( int gamePtr );
public static native void comms_getAddr( int gamePtr, CommsAddrRec addr );
public static native void comms_setAddr( int gamePtr, CommsAddrRec addr );
}

View file

@ -6,5 +6,6 @@ cd $BASE/../XWords4/bin/classes
javah -o /tmp/javah$$.txt org.eehouse.android.xw4.jni.XwJNI
javap -s org.eehouse.android.xw4.jni.DrawCtx
javap -s org.eehouse.android.xw4.jni.XW_UtilCtxt
javap -s org.eehouse.android.xw4.jni.CommsAddrRec
cat /tmp/javah$$.txt
rm /tmp/javah$$.txt