handle GCM messages containing data, changing clientVers so server

knows we can.  And send to relay in AsyncTask rather than UI thread.
This commit is contained in:
Eric House 2013-05-22 06:15:07 -07:00
parent 076b1b7543
commit 120748416b
3 changed files with 120 additions and 46 deletions

View file

@ -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 \

View file

@ -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 );

View file

@ -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" );
}