Successfully send text via NFC and log it on receiver

This commit is contained in:
Eric House 2013-11-11 21:36:19 -08:00
parent 98989abb14
commit a88835a4a1
9 changed files with 108 additions and 54 deletions

View file

@ -29,7 +29,7 @@
<!-- BE SURE TO MODIFY project.project AND the variable TARGET in <!-- BE SURE TO MODIFY project.project AND the variable TARGET in
../scripts/setup_local_props.sh if targetSdkVersion changes!!! ../scripts/setup_local_props.sh if targetSdkVersion changes!!!
--> -->
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="11" /> <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="14" />
<supports-screens android:resizeable="true" <supports-screens android:resizeable="true"
android:smallScreens="true" android:smallScreens="true"
@ -51,6 +51,7 @@
<uses-feature android:name="android.hardware.telephony" <uses-feature android:name="android.hardware.telephony"
android:required = "false" android:required = "false"
/> />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<!-- GCM stuff --> <!-- GCM stuff -->
<permission android:name="org.eehouse.android.xw4.permission.C2D_MESSAGE" <permission android:name="org.eehouse.android.xw4.permission.C2D_MESSAGE"
@ -59,6 +60,7 @@
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.NFC" />
<application android:icon="@drawable/icon48x48" <application android:icon="@drawable/icon48x48"
android:label="@string/app_name" android:label="@string/app_name"
@ -74,6 +76,13 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/org.eehouse.android.xw4" />
</intent-filter>
</activity> </activity>
<activity android:name="DictsActivity" <activity android:name="DictsActivity"

View file

@ -11,4 +11,4 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target. # Project target.
target=Google Inc.:Google APIs:11 target=Google Inc.:Google APIs:14

View file

@ -1187,6 +1187,7 @@
two buttons in the dialog. --> two buttons in the dialog. -->
<string name="button_text">SMS/Text</string> <string name="button_text">SMS/Text</string>
<string name="button_html">Email</string> <string name="button_html">Email</string>
<string name="button_nfc">NFC</string>
<!-- This is the subject line of the email/text sent to invite <!-- This is the subject line of the email/text sent to invite
someone to join a game. --> someone to join a game. -->

View file

@ -905,8 +905,7 @@ public class BoardActivity extends XWActivity
{ {
if ( LAUNCH_INVITE_ACTION == id ) { if ( LAUNCH_INVITE_ACTION == id ) {
if ( DlgDelegate.DISMISS_BUTTON != which ) { if ( DlgDelegate.DISMISS_BUTTON != which ) {
GameUtils.launchInviteActivity( BoardActivity.this, GameUtils.launchInviteActivity( this, which,
DlgDelegate.EMAIL_BTN == which,
m_room, null, m_gi.dictLang, m_room, null, m_gi.dictLang,
m_gi.dictName, m_gi.nPlayers ); m_gi.dictName, m_gi.nPlayers );
} }

View file

@ -49,6 +49,7 @@ public class DlgDelegate {
public static final int SMS_BTN = AlertDialog.BUTTON_POSITIVE; public static final int SMS_BTN = AlertDialog.BUTTON_POSITIVE;
public static final int EMAIL_BTN = AlertDialog.BUTTON_NEGATIVE; public static final int EMAIL_BTN = AlertDialog.BUTTON_NEGATIVE;
public static final int NFC_BTN = AlertDialog.BUTTON_NEUTRAL;
public static final int DISMISS_BUTTON = 0; public static final int DISMISS_BUTTON = 0;
public static final int SKIP_CALLBACK = -1; public static final int SKIP_CALLBACK = -1;
@ -404,12 +405,16 @@ public class DlgDelegate {
private Dialog createHtmlThenDialog( DlgState state, int id ) private Dialog createHtmlThenDialog( DlgState state, int id )
{ {
OnClickListener lstnr = mkCallbackClickListener( state ); OnClickListener lstnr = mkCallbackClickListener( state );
Dialog dialog = new AlertDialog.Builder( m_activity ) AlertDialog.Builder builder = new AlertDialog.Builder( m_activity )
.setTitle( R.string.query_title ) .setTitle( R.string.query_title )
.setMessage( R.string.sms_or_email ) .setMessage( R.string.sms_or_email )
.setPositiveButton( R.string.button_text, lstnr ) .setPositiveButton( R.string.button_text, lstnr )
.setNegativeButton( R.string.button_html, lstnr ) .setNegativeButton( R.string.button_html, lstnr );
.create();
if ( XWApp.NFC_ENABLED ) {
builder.setNeutralButton( R.string.button_nfc, lstnr );
}
Dialog dialog = builder.create();
return setCallbackDismissListener( dialog, state, id ); return setCallbackDismissListener( dialog, state, id );
} }

View file

@ -26,11 +26,17 @@ import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Rect; import android.graphics.Rect;
import android.net.Uri; import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.text.Html; import android.text.Html;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.Display; import android.view.Display;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.nio.charset.Charset;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -534,8 +540,7 @@ public class GameUtils {
nPlayersT, nPlayersH, null, gameID, isHost ); nPlayersT, nPlayersH, null, gameID, isHost );
} }
public static void launchInviteActivity( Context context, public static void launchInviteActivity( Activity activity, int chosen,
boolean choseEmail,
String room, String inviteID, String room, String inviteID,
int lang, String dict, int lang, String dict,
int nPlayers ) int nPlayers )
@ -543,51 +548,67 @@ public class GameUtils {
if ( null == inviteID ) { if ( null == inviteID ) {
inviteID = makeRandomID(); inviteID = makeRandomID();
} }
Uri gameUri = NetLaunchInfo.makeLaunchUri( context, room, inviteID, Uri gameUri = NetLaunchInfo.makeLaunchUri( activity, room, inviteID,
lang, dict, nPlayers ); lang, dict, nPlayers );
if ( null != gameUri ) { if ( null != gameUri ) {
int fmtId = choseEmail? R.string.invite_htmf : R.string.invite_txtf; if ( DlgDelegate.NFC_BTN == chosen ) {
int choiceID; DbgUtils.logf( "wants to launch NFC" );
String message = context.getString( fmtId, gameUri.toString() ); NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter( activity );
NdefMessage msg = new NdefMessage( new NdefRecord[] {
Intent intent = new Intent(); new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
if ( choseEmail ) { "application/org.eehouse.android.xw4"
intent.setAction( Intent.ACTION_SEND ); .getBytes(Charset.forName("US-ASCII")),
String subject = new byte[0], "Beam me up, Android!"
Utils.format( context, R.string.invite_subjectf, room ); .getBytes(Charset.forName("US-ASCII")))
intent.putExtra( Intent.EXTRA_SUBJECT, subject ); ,NdefRecord.createApplicationRecord("org.eehouse.android.xw4")
intent.putExtra( Intent.EXTRA_TEXT, Html.fromHtml(message) ); });
nfcAdapter.setNdefPushMessage( msg, activity );
File attach = null; Utils.showToast( activity, "Tap the receiving device now" );
File tmpdir = XWApp.ATTACH_SUPPORTED ?
DictUtils.getDownloadDir( context ) : null;
if ( null != tmpdir ) { // no attachment
attach = makeJsonFor( tmpdir, room, inviteID, lang,
dict, nPlayers );
}
if ( null == attach ) { // no attachment
intent.setType( "message/rfc822");
} else {
String mime = context.getString( R.string.invite_mime );
intent.setType( mime );
Uri uri = Uri.fromFile( attach );
intent.putExtra( Intent.EXTRA_STREAM, uri );
}
choiceID = R.string.invite_chooser_email;
} else { } else {
intent.setAction( Intent.ACTION_VIEW ); boolean choseEmail = DlgDelegate.EMAIL_BTN == chosen;
intent.setType( "vnd.android-dir/mms-sms" );
intent.putExtra( "sms_body", message );
choiceID = R.string.invite_chooser_sms;
}
String choiceType = context.getString( choiceID ); int fmtId = choseEmail? R.string.invite_htmf : R.string.invite_txtf;
String chooserMsg = int choiceID;
Utils.format( context, R.string.invite_chooserf, choiceType ); String message = activity.getString( fmtId, gameUri.toString() );
context.startActivity( Intent.createChooser( intent, chooserMsg ) );
Intent intent = new Intent();
if ( choseEmail ) {
intent.setAction( Intent.ACTION_SEND );
String subject =
Utils.format( activity, R.string.invite_subjectf, room );
intent.putExtra( Intent.EXTRA_SUBJECT, subject );
intent.putExtra( Intent.EXTRA_TEXT, Html.fromHtml(message) );
File attach = null;
File tmpdir = XWApp.ATTACH_SUPPORTED ?
DictUtils.getDownloadDir( activity ) : null;
if ( null != tmpdir ) { // no attachment
attach = makeJsonFor( tmpdir, room, inviteID, lang,
dict, nPlayers );
}
if ( null == attach ) { // no attachment
intent.setType( "message/rfc822");
} else {
String mime = activity.getString( R.string.invite_mime );
intent.setType( mime );
Uri uri = Uri.fromFile( attach );
intent.putExtra( Intent.EXTRA_STREAM, uri );
}
choiceID = R.string.invite_chooser_email;
} else {
intent.setAction( Intent.ACTION_VIEW );
intent.setType( "vnd.android-dir/mms-sms" );
intent.putExtra( "sms_body", message );
choiceID = R.string.invite_chooser_sms;
}
String choiceType = activity.getString( choiceID );
String chooserMsg =
Utils.format( activity, R.string.invite_chooserf, choiceType );
activity.startActivity( Intent.createChooser( intent, chooserMsg ) );
}
} }
} }

View file

@ -28,9 +28,13 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.Parcelable;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -1123,6 +1127,19 @@ public class GamesList extends XWExpandableListActivity
} }
} }
private void tryNFCIntent( Intent intent )
{
if ( NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) ) {
Parcelable[] rawMsgs =
intent.getParcelableArrayExtra( NfcAdapter.EXTRA_NDEF_MESSAGES );
// only one message sent during the beam
NdefMessage msg = (NdefMessage) rawMsgs[0];
// record 0 contains the MIME type, record 1 is the AAR, if present
String txt = new String( msg.getRecords()[0].getPayload() );
DbgUtils.logf( "got message: %s", txt );
}
}
private void askDefaultNameIf() private void askDefaultNameIf()
{ {
if ( null == CommonPrefs.getDefaultPlayerName( this, 0, false ) ) { if ( null == CommonPrefs.getDefaultPlayerName( this, 0, false ) ) {
@ -1253,6 +1270,7 @@ public class GamesList extends XWExpandableListActivity
startHasGameID( intent ); startHasGameID( intent );
startHasRowID( intent ); startHasRowID( intent );
tryAlert( intent ); tryAlert( intent );
tryNFCIntent( intent );
} }
private void doOpenGame( Object[] params ) private void doOpenGame( Object[] params )

View file

@ -158,7 +158,7 @@ public class NewGameActivity extends XWActivity {
switch( id ) { switch( id ) {
case NEW_GAME_ACTION: case NEW_GAME_ACTION:
if ( DlgDelegate.DISMISS_BUTTON != which ) { if ( DlgDelegate.DISMISS_BUTTON != which ) {
makeNewGame( true, true, DlgDelegate.EMAIL_BTN == which ); makeNewGame( true, true, which );
} }
break; break;
default: default:
@ -311,12 +311,12 @@ public class NewGameActivity extends XWActivity {
// Let 'em cancel before we make the game // Let 'em cancel before we make the game
showEmailOrSMSThen( NEW_GAME_ACTION ); showEmailOrSMSThen( NEW_GAME_ACTION );
} else { } else {
makeNewGame( networked, launch, false ); makeNewGame( networked, launch, DlgDelegate.SMS_BTN );
} }
} }
private void makeNewGame( boolean networked, boolean launch, private void makeNewGame( boolean networked, boolean launch,
boolean choseEmail ) int chosen )
{ {
String room = null; String room = null;
String inviteID = null; String inviteID = null;
@ -337,7 +337,7 @@ public class NewGameActivity extends XWActivity {
if ( launch ) { if ( launch ) {
GameUtils.launchGame( this, rowid, networked ); GameUtils.launchGame( this, rowid, networked );
if ( networked ) { if ( networked ) {
GameUtils.launchInviteActivity( this, choseEmail, room, GameUtils.launchInviteActivity( this, chosen, room,
inviteID, lang[0], dict[0], inviteID, lang[0], dict[0],
nPlayers ); nPlayers );
} }

View file

@ -40,6 +40,7 @@ public class XWApp extends Application {
public static final boolean DEBUG_EXP_TIMERS = false && DEBUG; public static final boolean DEBUG_EXP_TIMERS = false && DEBUG;
public static final boolean GCM_IGNORED = false; public static final boolean GCM_IGNORED = false;
public static final boolean UDP_ENABLED = true; public static final boolean UDP_ENABLED = true;
public static final boolean NFC_ENABLED = true;
public static final String SMS_PUBLIC_HEADER = "-XW4"; public static final String SMS_PUBLIC_HEADER = "-XW4";
public static final int MAX_TRAY_TILES = 7; // comtypes.h public static final int MAX_TRAY_TILES = 7; // comtypes.h