From 120748416b7fc1640604f9496461ff3c5fc0f3f2 Mon Sep 17 00:00:00 2001 From: Eric House <xwords@eehouse.org> Date: Wed, 22 May 2013 06:15:07 -0700 Subject: [PATCH] handle GCM messages containing data, changing clientVers so server knows we can. And send to relay in AsyncTask rather than UI thread. --- xwords4/android/XWords4/jni/Android.mk | 2 +- .../eehouse/android/xw4/GCMIntentService.java | 9 + .../org/eehouse/android/xw4/RelayService.java | 155 +++++++++++++----- 3 files changed, 120 insertions(+), 46 deletions(-) diff --git a/xwords4/android/XWords4/jni/Android.mk b/xwords4/android/XWords4/jni/Android.mk index 67a4961aa..2c72a0f92 100644 --- a/xwords4/android/XWords4/jni/Android.mk +++ b/xwords4/android/XWords4/jni/Android.mk @@ -36,7 +36,7 @@ local_DEFINES += \ -DHASH_STREAM \ -DXWFEATURE_BASE64 \ -DXWFEATURE_DEVID \ - -DINITIAL_CLIENT_VERS=2 \ + -DINITIAL_CLIENT_VERS=3 \ -DRELAY_ROOM_DEFAULT=\"\" \ -D__LITTLE_ENDIAN \ diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java index 532e70329..23285a1fa 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GCMIntentService.java @@ -62,6 +62,15 @@ public class GCMIntentService extends GCMBaseIntentService { if ( null != value && Boolean.parseBoolean( value ) ) { RelayReceiver.RestartTimer( context, true ); } + + value = intent.getStringExtra( "msg64" ); + if ( null != value ) { + String connname = intent.getStringExtra( "connname" ); + if ( null != connname ) { + RelayService.processMsg( context, connname, value ); + } + } + value = intent.getStringExtra( "checkUpdates" ); if ( null != value && Boolean.parseBoolean( value ) ) { UpdateCheckReceiver.checkVersions( context, true ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java index bc4d2d179..0c2afed9f 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/RelayService.java @@ -23,6 +23,7 @@ package org.eehouse.android.xw4; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.IBinder; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -32,11 +33,34 @@ import java.util.HashMap; import java.util.Iterator; import org.eehouse.android.xw4.jni.GameSummary; +import org.eehouse.android.xw4.jni.XwJNI; public class RelayService extends Service { private static final int MAX_SEND = 1024; private static final int MAX_BUF = MAX_SEND - 2; + private static final String CMD_STR = "CMD"; + private static final int PROCESS_MSG = 1; + private static final String MSG = "MSG"; + private static final String RELAY_ID = "RELAY_ID"; + + public static void processMsg( Context context, String relayId, + String msg64 ) + { + byte[] msg = XwJNI.base64Decode( msg64 ); + Intent intent = getIntentTo( context, PROCESS_MSG ) + .putExtra( MSG, msg ) + .putExtra( RELAY_ID, relayId ); + context.startService( intent ); + } + + private static Intent getIntentTo( Context context, int cmd ) + { + Intent intent = new Intent( context, RelayService.class ); + intent.putExtra( CMD_STR, cmd ); + return intent; + } + @Override public void onCreate() { @@ -57,6 +81,26 @@ public class RelayService extends Service { return null; } + @Override + public int onStartCommand( Intent intent, int flags, int startId ) + { + int cmd = intent.getIntExtra( CMD_STR, -1 ); + switch( cmd ) { + case PROCESS_MSG: + String[] relayIDs = new String[1]; + relayIDs[0] = intent.getStringExtra( RELAY_ID ); + long[] rowIDs = DBUtils.getRowIDsFor( this, relayIDs[0] ); + if ( 0 < rowIDs.length ) { + byte[][][] msgs = new byte[1][1][1]; + msgs[0][0] = intent.getByteArrayExtra( MSG ); + process( msgs, rowIDs, relayIDs ); + } + break; + } + stopSelf( startId ); + return Service.START_NOT_STICKY; + } + private void setupNotification( String[] relayIDs ) { for ( String relayID : relayIDs ) { @@ -80,67 +124,80 @@ public class RelayService extends Service { long[][] rowIDss = new long[1][]; String[] relayIDs = DBUtils.getRelayIDs( this, rowIDss ); if ( null != relayIDs && 0 < relayIDs.length ) { - long[] rowIDs = rowIDss[0]; byte[][][] msgs = NetUtils.queryRelay( this, relayIDs ); - - if ( null != msgs ) { - RelayMsgSink sink = new RelayMsgSink(); - int nameCount = relayIDs.length; - ArrayList<String> idsWMsgs = - new ArrayList<String>( nameCount ); - for ( int ii = 0; ii < nameCount; ++ii ) { - byte[][] forOne = msgs[ii]; - // if game has messages, open it and feed 'em - // to it. - if ( null == forOne ) { - // Nothing for this relayID - } else if ( BoardActivity.feedMessages( rowIDs[ii], forOne ) - || GameUtils.feedMessages( this, rowIDs[ii], - forOne, null, - sink ) ) { - idsWMsgs.add( relayIDs[ii] ); - } else { - DbgUtils.logf( "dropping message for %s (rowid %d)", - relayIDs[ii], rowIDs[ii] ); - } - } - if ( 0 < idsWMsgs.size() ) { - String[] tmp = new String[idsWMsgs.size()]; - idsWMsgs.toArray( tmp ); - setupNotification( tmp ); - } - sink.send( this ); - } + process( msgs, rowIDss[0], relayIDs ); } } - private static void sendToRelay( Context context, - HashMap<String,ArrayList<byte[]>> msgHash ) + private void process( byte[][][] msgs, long[] rowIDs, String[] relayIDs ) { - // format: total msg lenth: 2 - // number-of-relayIDs: 2 - // for-each-relayid: relayid + '\n': varies - // message count: 1 - // for-each-message: length: 2 - // message: varies + if ( null != msgs ) { + RelayMsgSink sink = new RelayMsgSink(); + int nameCount = relayIDs.length; + ArrayList<String> idsWMsgs = new ArrayList<String>( nameCount ); - if ( null != msgHash ) { + for ( int ii = 0; ii < nameCount; ++ii ) { + byte[][] forOne = msgs[ii]; + + // if game has messages, open it and feed 'em to it. + if ( null == forOne ) { + // Nothing for this relayID + } else if ( BoardActivity.feedMessages( rowIDs[ii], forOne ) + || GameUtils.feedMessages( this, rowIDs[ii], + forOne, null, + sink ) ) { + idsWMsgs.add( relayIDs[ii] ); + } else { + DbgUtils.logf( "message for %s (rowid %d) not consumed", + relayIDs[ii], rowIDs[ii] ); + } + } + if ( 0 < idsWMsgs.size() ) { + String[] tmp = new String[idsWMsgs.size()]; + idsWMsgs.toArray( tmp ); + setupNotification( tmp ); + } + sink.send( this ); + } + } + + private static class AsyncSender extends AsyncTask<Void, Void, Void> { + private Context m_context; + private HashMap<String,ArrayList<byte[]>> m_msgHash; + + public AsyncSender( Context context, + HashMap<String,ArrayList<byte[]>> msgHash ) + { + m_context = context; + m_msgHash = msgHash; + } + + @Override + protected Void doInBackground( Void... ignored ) + { + // format: total msg lenth: 2 + // number-of-relayIDs: 2 + // for-each-relayid: relayid + '\n': varies + // message count: 1 + // for-each-message: length: 2 + // message: varies + + // Build up a buffer containing everything but the total + // message length and number of relayIDs in the message. try { - // Build up a buffer containing everything but the total - // message length and number of relayIDs in the message. ByteArrayOutputStream store = new ByteArrayOutputStream( MAX_BUF ); // mem DataOutputStream outBuf = new DataOutputStream( store ); int msgLen = 4; // relayID count + protocol stuff int nRelayIDs = 0; - Iterator<String> iter = msgHash.keySet().iterator(); + Iterator<String> iter = m_msgHash.keySet().iterator(); while ( iter.hasNext() ) { String relayID = iter.next(); int thisLen = 1 + relayID.length(); // string and '\n' thisLen += 2; // message count - ArrayList<byte[]> msgs = msgHash.get( relayID ); + ArrayList<byte[]> msgs = m_msgHash.get( relayID ); for ( byte[] msg : msgs ) { thisLen += 2 + msg.length; } @@ -161,10 +218,9 @@ public class RelayService extends Service { } msgLen += thisLen; } - // Now open a real socket, write size and proto, and // copy in the formatted buffer - Socket socket = NetUtils.makeProxySocket( context, 8000 ); + Socket socket = NetUtils.makeProxySocket( m_context, 8000 ); if ( null != socket ) { DataOutputStream outStream = new DataOutputStream( socket.getOutputStream() ); @@ -179,6 +235,15 @@ public class RelayService extends Service { } catch ( java.io.IOException ioe ) { DbgUtils.loge( ioe ); } + return null; + } // doInBackground + } + + private static void sendToRelay( Context context, + HashMap<String,ArrayList<byte[]>> msgHash ) + { + if ( null != msgHash ) { + new AsyncSender( context, msgHash ).execute(); } else { DbgUtils.logf( "sendToRelay: null msgs" ); }