wifi: make invitations work

Add UI, minor thanks to recent refactoring, to allow invitations via
wifi direct. Uses a mapping of all currently known device mac addresses
to names, with only the latter shown to users. Works well, though
something I changed seems to have causes devices to start losing track
of their connections to each other.
This commit is contained in:
Eric House 2016-11-21 21:10:16 -08:00
parent 3f0bef48f6
commit e0f0666b1c
13 changed files with 726 additions and 401 deletions

View file

@ -95,7 +95,10 @@
android:label="@string/relay_invite_title"
android:configChanges="keyboardHidden|orientation|screenSize"
/>
<activity android:name="WiDirInviteActivity"
android:label="@string/p2p_invite_title"
android:configChanges="keyboardHidden|orientation|screenSize"
/>
<activity android:name="GameConfigActivity"
android:screenOrientation="sensor"
android:configChanges="keyboardHidden|orientation|screenSize"

View file

@ -142,3 +142,5 @@ DualpaneDelegate.java
BoardContainer.java
BiDiSockWrap.java
WiDirService.java
WiDirInviteActivity.java
WiDirInviteDelegate.java

View file

@ -92,6 +92,10 @@
android:label="@string/relay_invite_title"
android:configChanges="keyboardHidden|orientation|screenSize"
/>
<activity android:name="WiDirInviteActivity"
android:label="@string/p2p_invite_title"
android:configChanges="keyboardHidden|orientation|screenSize"
/>
<activity android:name="GameConfigActivity"
android:screenOrientation="sensor"

File diff suppressed because it is too large Load diff

View file

@ -403,7 +403,7 @@
when user attempts to play word not in the wordlist. -->
<string name="phonies_disallow">Disallow phonies</string>
<!-- Shown when using the the Game configure screen to configure a
<!-- Shown when using the Game configure screen to configure a
networked game and you try to make all players local. -->
<string name="str_reg_server_sans_remote">At least one player must
be marked \"Remote\" for a game started as Host.</string>
@ -975,7 +975,7 @@
<string name="prefs_colors_summary">Edit colors used on the board</string>
<!-- The remaining strings (down to the color edit dialog below)
are showns as the names of editable colors and as the the
are showns as the names of editable colors and as the
title of the color editor that comes up when the name is
tapped. -->
<!-- (color for) double-letter bonus squares on the board -->
@ -1921,6 +1921,7 @@
<!-- Title of phone number picker during invitation to a game via SMS -->
<string name="sms_invite_title">SMS Invitation</string>
<string name="relay_invite_title">Relay Invitation</string>
<string name="p2p_invite_title">WiFi Direct Invitation</string>
<!-- -->
<string name="game_btname_title">Bluetooth game name</string>
@ -1956,6 +1957,20 @@
<item quantity="other">Please check the %1$d devices you want to invite
to your new game, then tap \"%2$s\".</item>
</plurals>
<!-- -->
<plurals name="invite_p2p_desc_fmt">
<item quantity="one">Please select the name of the
WiFiDirect device you want to invite to your new game, then tap
\"%2$s\".</item>
<item quantity="other">Please select the %1$d WiFiDirect device names you
want to invite to your new game, then tap \"%2$s\".</item>
</plurals>
<string name="invite_p2p_desc_extra">Only devices that are
currently available are shown. If a nearby device isn\'t showing
up please make sure that WiFi is turned on, that Crosswords is
installed, and that play via WiFi Direct is enabled.</string>
<!-- -->
<string name="manual_owner_name">(Not in contacts)</string>
<!-- -->
@ -1965,6 +1980,11 @@
<string name="empty_sms_inviter">This phone list is empty. Use the
\"Import contact\" button to add people you want to invite, the +
button to enter numbers directly.</string>
<!-- Shows in WiFiDirect Invite dialog when no known peers -->
<string name="empty_p2p_inviter">There are currently no devices
reachable via WiFiDirect that have Crosswords installed.</string>
<!-- -->
<string name="empty_relay_inviter">This list of devices is
empty. Use the \"Scan games\" button to scan your old games

View file

@ -342,7 +342,7 @@
<!-- Don't warn, but simply force to skip turn (give 0 points)
when user attempts to play word not in the wordlist. -->
<string name="phonies_disallow">Wollasid seinohp</string>
<!-- Shown when using the the Game configure screen to configure a
<!-- Shown when using the Game configure screen to configure a
networked game and you try to make all players local. -->
<string name="str_reg_server_sans_remote">Ta tsael eno reyalp tsum
eb dekram \"Etomer\" rof a emag detrats sa Tsoh.</string>
@ -839,7 +839,7 @@
<!-- clarification of the above -->
<string name="prefs_colors_summary">Tide sroloc desu no eht draob</string>
<!-- The remaining strings (down to the color edit dialog below)
are showns as the names of editable colors and as the the
are showns as the names of editable colors and as the
title of the color editor that comes up when the name is
tapped. -->
<!-- (color for) double-letter bonus squares on the board -->
@ -1657,6 +1657,7 @@
<!-- Title of phone number picker during invitation to a game via SMS -->
<string name="sms_invite_title">SMS Noitativni</string>
<string name="relay_invite_title">Yaler Noitativni</string>
<string name="p2p_invite_title">IfIw Tcerid Noitativni</string>
<!-- -->
<string name="game_btname_title">Htooteulb emag eman</string>
<!-- -->
@ -1692,6 +1693,18 @@
ot ruoy wen ,emag neht pat \"%2$s\".</item>
</plurals>
<!-- -->
<plurals name="invite_p2p_desc_fmt">
<item quantity="one">Esaelp tceles eht eman fo eht
TcErIdifiw ecived uoy tnaw ot etivni ot ruoy wen ,emag neht pat
\"%2$s\".</item>
<item quantity="other">Esaelp tceles eht %1$d TcErIdifiw ecived seman uoy
tnaw ot etivni ot ruoy wen ,emag neht pat \"%2$s\".</item>
</plurals>
<string name="invite_p2p_desc_extra">Ylno secived taht era
yltnerruc elbaliava era nwohs. Fi a ybraen ecived nsi\'t gniwohs
pu esaelp ekam erus taht IfIw si denrut ,no taht Sdrowssorc si
,dellatsni dna taht yalp aiv IfIw Tcerid si delbane.</string>
<!-- -->
<string name="manual_owner_name">tOn( ni )stcatnoc</string>
<!-- -->
<string name="warn_nomobile_fmt">Eht rebmun %1$s rof %2$s si ton
@ -1700,6 +1713,9 @@
<string name="empty_sms_inviter">Siht enohp tsil si ytpme. Esu eht
\"Tropmi tcatnoc\" nottub ot dda elpoep uoy tnaw ot ,etivni eht +
nottub ot retne srebmun yltcerid.</string>
<!-- Shows in WiFiDirect Invite dialog when no known peers -->
<string name="empty_p2p_inviter">Ereht era yltnerruc on secived
elbahcaer aiv TcErIdifiw taht evah Sdrowssorc dellatsni.</string>
<!-- -->
<string name="empty_relay_inviter">Siht tsil fo secived si
ytpme. Esu eht \"Nacs semag\" nottub ot nacs ruoy dlo semag

View file

@ -342,7 +342,7 @@
<!-- Don't warn, but simply force to skip turn (give 0 points)
when user attempts to play word not in the wordlist. -->
<string name="phonies_disallow">DISALLOW PHONIES</string>
<!-- Shown when using the the Game configure screen to configure a
<!-- Shown when using the Game configure screen to configure a
networked game and you try to make all players local. -->
<string name="str_reg_server_sans_remote">AT LEAST ONE PLAYER MUST
BE MARKED \"REMOTE\" FOR A GAME STARTED AS HOST.</string>
@ -839,7 +839,7 @@
<!-- clarification of the above -->
<string name="prefs_colors_summary">EDIT COLORS USED ON THE BOARD</string>
<!-- The remaining strings (down to the color edit dialog below)
are showns as the names of editable colors and as the the
are showns as the names of editable colors and as the
title of the color editor that comes up when the name is
tapped. -->
<!-- (color for) double-letter bonus squares on the board -->
@ -1657,6 +1657,7 @@
<!-- Title of phone number picker during invitation to a game via SMS -->
<string name="sms_invite_title">SMS INVITATION</string>
<string name="relay_invite_title">RELAY INVITATION</string>
<string name="p2p_invite_title">WIFI DIRECT INVITATION</string>
<!-- -->
<string name="game_btname_title">BLUETOOTH GAME NAME</string>
<!-- -->
@ -1692,6 +1693,18 @@
TO YOUR NEW GAME, THEN TAP \"%2$s\".</item>
</plurals>
<!-- -->
<plurals name="invite_p2p_desc_fmt">
<item quantity="one">PLEASE SELECT THE NAME OF THE
WIFIDIRECT DEVICE YOU WANT TO INVITE TO YOUR NEW GAME, THEN TAP
\"%2$s\".</item>
<item quantity="other">PLEASE SELECT THE %1$d WIFIDIRECT DEVICE NAMES YOU
WANT TO INVITE TO YOUR NEW GAME, THEN TAP \"%2$s\".</item>
</plurals>
<string name="invite_p2p_desc_extra">ONLY DEVICES THAT ARE
CURRENTLY AVAILABLE ARE SHOWN. IF A NEARBY DEVICE ISN\'T SHOWING
UP PLEASE MAKE SURE THAT WIFI IS TURNED ON, THAT CROSSWORDS IS
INSTALLED, AND THAT PLAY VIA WIFI DIRECT IS ENABLED.</string>
<!-- -->
<string name="manual_owner_name">(NOT IN CONTACTS)</string>
<!-- -->
<string name="warn_nomobile_fmt">THE NUMBER %1$s FOR %2$s IS NOT
@ -1700,6 +1713,9 @@
<string name="empty_sms_inviter">THIS PHONE LIST IS EMPTY. USE THE
\"IMPORT CONTACT\" BUTTON TO ADD PEOPLE YOU WANT TO INVITE, THE +
BUTTON TO ENTER NUMBERS DIRECTLY.</string>
<!-- Shows in WiFiDirect Invite dialog when no known peers -->
<string name="empty_p2p_inviter">THERE ARE CURRENTLY NO DEVICES
REACHABLE VIA WIFIDIRECT THAT HAVE CROSSWORDS INSTALLED.</string>
<!-- -->
<string name="empty_relay_inviter">THIS LIST OF DEVICES IS
EMPTY. USE THE \"SCAN GAMES\" BUTTON TO SCAN YOUR OLD GAMES

View file

@ -673,9 +673,9 @@ public class BoardDelegate extends DelegateBase
case RELAY_INVITE_RESULT:
missingMeans = InviteMeans.RELAY;
break;
// case P2P_INVITE_RESULT:
// missingMeans = InviteMeans.WIFIDIRECT;
// break;
case P2P_INVITE_RESULT:
missingMeans = InviteMeans.WIFIDIRECT;
break;
}
if ( null != missingMeans ) {
@ -1117,6 +1117,11 @@ public class BoardDelegate extends DelegateBase
RelayInviteDelegate.launchForResult( m_activity, m_nMissing,
RequestCode.RELAY_INVITE_RESULT );
break;
case WIFIDIRECT:
WiDirInviteDelegate.launchForResult( m_activity,
m_nMissing,
RequestCode.P2P_INVITE_RESULT );
break;
case EMAIL:
case CLIPBOARD:
NetLaunchInfo nli = new NetLaunchInfo( m_summary, m_gi, 1,
@ -2462,6 +2467,9 @@ public class BoardDelegate extends DelegateBase
DbgUtils.logex( nfi );
}
break;
case WIFIDIRECT:
WiDirService.inviteRemote( m_activity, dev, nli );
break;
}
if ( null != dev ) {

View file

@ -727,19 +727,19 @@ public class DlgDelegate {
items.add( getString( R.string.invite_choice_bt ) );
means.add( DlgClickNotify.InviteMeans.BLUETOOTH );
}
if ( XWApp.RELAYINVITE_SUPPORTED ) {
items.add( getString( R.string.invite_choice_relay ) );
means.add( DlgClickNotify.InviteMeans.RELAY );
}
if ( WiDirService.supported() ) {
items.add( getString( R.string.invite_choice_p2p ) );
means.add( DlgClickNotify.InviteMeans.WIFIDIRECT );
}
if ( XWPrefs.getNFCToSelfEnabled( m_activity )
|| NFCUtils.nfcAvail( m_activity )[0] ) {
items.add( getString( R.string.invite_choice_nfc ) );
means.add( DlgClickNotify.InviteMeans.NFC );
}
if ( XWApp.RELAYINVITE_SUPPORTED ) {
items.add( getString( R.string.invite_choice_relay ) );
means.add( DlgClickNotify.InviteMeans.RELAY );
}
// if ( WiDirService.supported() ) {
// items.add( getString( R.string.invite_choice_p2p ) );
// means.add( DlgClickNotify.InviteMeans.WIFIDIRECT );
// }
items.add( getString( R.string.slmenu_copy_sel ) );
means.add( DlgClickNotify.InviteMeans.CLIPBOARD );

View file

@ -28,7 +28,7 @@ public enum RequestCode {
BT_INVITE_RESULT,
SMS_INVITE_RESULT,
RELAY_INVITE_RESULT,
// P2P_INVITE_RESULT,
P2P_INVITE_RESULT,
// PermUtils
PERM_REQUEST,

View file

@ -0,0 +1,35 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2012 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4;
import android.os.Bundle;
public class WiDirInviteActivity extends InviteActivity {
private WiDirInviteDelegate m_dlgt;
@Override
protected void onCreate( Bundle savedInstanceState )
{
m_dlgt = new WiDirInviteDelegate( this, savedInstanceState );
super.onCreate( savedInstanceState, m_dlgt );
}
}

View file

@ -0,0 +1,104 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2016 by Eric House (xwords@eehouse.org). All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4;
import android.widget.ArrayAdapter;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.content.Intent;
import java.util.Map;
import java.util.Iterator;
import junit.framework.Assert;
public class WiDirInviteDelegate extends InviteDelegate
implements WiDirService.DevSetListener {
private static final String SAVE_NAME = "SAVE_NAME";
private Map<String, String> m_macsToName;
private Activity m_activity;
public static void launchForResult( Activity activity, int nMissing,
RequestCode requestCode )
{
Intent intent = new Intent( activity, WiDirInviteActivity.class );
intent.putExtra( INTENT_KEY_NMISSING, nMissing );
activity.startActivityForResult( intent, requestCode.ordinal() );
}
public WiDirInviteDelegate( Delegator delegator, Bundle savedInstanceState )
{
super( delegator, savedInstanceState, R.layout.inviter );
m_activity = delegator.getActivity();
}
@Override
protected void init( Bundle savedInstanceState )
{
String msg = getString( R.string.button_invite );
msg = getQuantityString( R.plurals.invite_p2p_desc_fmt, m_nMissing,
m_nMissing, msg );
msg += "\n\n" + getString( R.string.invite_p2p_desc_extra );
super.init( R.id.button_invite, R.id.invite_desc, msg );
}
@Override
protected void onResume()
{
super.onResume();
WiDirService.registerDevSetListener( this );
}
@Override
protected void onPause()
{
super.onPause();
WiDirService.unregisterDevSetListener( this );
}
// DevSetListener interface
public void setChanged( Map<String, String> macToName )
{
m_macsToName = macToName;
runOnUiThread( new Runnable() {
@Override
public void run() {
rebuildList();
}
} );
}
private void rebuildList()
{
int count = m_macsToName.size();
String[] names = new String[count];
String[] addrs = new String[count];
Iterator<String> iter = m_macsToName.keySet().iterator();
for ( int ii = 0; ii < count; ++ii ) {
String mac = iter.next();
addrs[ii] = mac;
names[ii] = m_macsToName.get(mac);
}
updateListAdapter( R.layout.inviter_item, names, addrs, false );
}
}

View file

@ -51,11 +51,13 @@ import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Collection;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -87,8 +89,9 @@ public class WiDirService extends XWService {
private static final String KEY_GAMEID = "gmid";
private static final String KEY_DATA = "data";
private static final String KEY_MAC = "myMac";
private static final String KEY_MAC = "mac";
private static final String KEY_NAME = "name";
private static final String KEY_MAP = "map";
private static final String KEY_RETADDR = "raddr";
private static final String CMD_PING = "ping";
@ -111,12 +114,19 @@ public class WiDirService extends XWService {
private static BiDiSockWrap.Iface sIface;
private static Map<String, BiDiSockWrap> sSocketWrapMap
= new HashMap<String, BiDiSockWrap>();
private static Map<String, String> sUserMap = new HashMap<String, String>();
private static Map<String, Long> sPendingDevs = new HashMap<String, Long>();
private static String sMacAddress;
private static String sDeviceName;
private static Set<DevSetListener> s_devListeners
= new HashSet<DevSetListener>();
private P2pMsgSink m_sink;
public interface DevSetListener {
void setChanged( Map<String, String> macToName );
}
@Override
public void onCreate()
{
@ -192,21 +202,36 @@ public class WiDirService extends XWService {
public static String formatNetStateInfo()
{
return String.format( "name: %s; mac: %s; role: %s; nThreads: %d",
sDeviceName, getMyMacAddress(),
sAmServer ? "owner" : "guest",
String map = mapToString( copyUserMap() );
return String.format( "map: %s role: %s; nThreads: %d",
map, sAmServer ? "owner" : "guest",
Thread.activeCount() );
}
private static String getMyMacAddress() { return getMyMacAddress(null); }
public static void registerDevSetListener( DevSetListener dsl )
{
synchronized( s_devListeners ) {
s_devListeners.add( dsl );
}
updateListeners();
}
public static void unregisterDevSetListener( DevSetListener dsl )
{
synchronized( s_devListeners ) {
s_devListeners.remove( dsl );
}
}
public static void inviteRemote( Context context, String macAddr,
NetLaunchInfo nli )
{
DbgUtils.logd( CLAZZ, "inviteRemote(%s)", macAddr );
Assert.assertNotNull( macAddr );
String nliString = nli.toString();
DbgUtils.logd( CLAZZ, "inviteRemote(%s)", nliString );
// String nliData = intent.getStringExtra( KEY_DATA );
// String macAddr = intent.getStringExtra( KEY_DEST );
boolean[] forwarding = { false };
BiDiSockWrap wrap = getForSend( macAddr, forwarding );
@ -256,7 +281,7 @@ public class WiDirService extends XWService {
DbgUtils.logex( jse );
}
} else {
DbgUtils.logd( CLAZZ, "no socket for packet for %s", macAddr );
DbgUtils.logd( CLAZZ, "sendPacket: no socket for %s", macAddr );
}
return nSent;
}
@ -343,25 +368,25 @@ public class WiDirService extends XWService {
}
};
if ( BuildConfig.DEBUG ) {
sGroupListener = new GroupInfoListener() {
public void onGroupInfoAvailable( WifiP2pGroup group ) {
if ( null == group ) {
DbgUtils.logd( CLAZZ, "onGroupInfoAvailable(null)!" );
} else {
DbgUtils.logd( CLAZZ, "onGroupInfoAvailable(owner: %b)!",
group.isGroupOwner() );
Assert.assertTrue( sAmGroupOwner == group.isGroupOwner() );
if ( sAmGroupOwner ) {
Collection<WifiP2pDevice> devs = group.getClientList();
sGroupListener = new GroupInfoListener() {
public void onGroupInfoAvailable( WifiP2pGroup group ) {
if ( null == group ) {
DbgUtils.logd( CLAZZ, "onGroupInfoAvailable(null)!" );
} else {
DbgUtils.logd( CLAZZ, "onGroupInfoAvailable(owner: %b)!",
group.isGroupOwner() );
Assert.assertTrue( sAmGroupOwner == group.isGroupOwner() );
if ( sAmGroupOwner ) {
Collection<WifiP2pDevice> devs = group.getClientList();
synchronized( sUserMap ) {
for ( WifiP2pDevice dev : devs ) {
String macAddr = dev.deviceAddress;
// DbgUtils.logd( CLAZZ, "group member: %s/%s",
// dev.deviceAddress,
// dev.deviceName );
sUserMap.put( macAddr, dev.deviceName );
BiDiSockWrap wrap = sSocketWrapMap.get( macAddr );
if ( null == wrap ) {
DbgUtils.logd( CLAZZ, "no socket for %s", macAddr );
DbgUtils.logd( CLAZZ,
"groupListener: no socket for %s",
macAddr );
} else {
DbgUtils.logd( CLAZZ, "socket for %s connected: %b",
macAddr, wrap.isConnected() );
@ -369,16 +394,16 @@ public class WiDirService extends XWService {
}
}
}
DbgUtils.logd( CLAZZ, "thread count: %d", Thread.activeCount() );
new Handler().postDelayed( new Runnable() {
@Override
public void run() {
getMgr().requestGroupInfo( sChannel, sGroupListener );
}
}, 60 * 1000 );
}
};
}
DbgUtils.logd( CLAZZ, "thread count: %d", Thread.activeCount() );
new Handler().postDelayed( new Runnable() {
@Override
public void run() {
getMgr().requestGroupInfo( sChannel, sGroupListener );
}
}, 60 * 1000 );
}
};
sIntentFilter = new IntentFilter();
sIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
@ -686,14 +711,17 @@ public class WiDirService extends XWService {
if ( cmd.equals( CMD_PING ) ) {
storeByAddress( wrap, asObj );
try {
wrap.send( new JSONObject()
.put( KEY_CMD, CMD_PONG )
.put( KEY_MAC, getMyMacAddress() ) );
JSONObject packet = new JSONObject()
.put( KEY_CMD, CMD_PONG )
.put( KEY_MAC, getMyMacAddress() );
addMappings( packet );
wrap.send( packet );
} catch ( JSONException jse ) {
DbgUtils.logex( jse );
}
} else if ( cmd.equals( CMD_PONG ) ) {
storeByAddress( wrap, asObj );
readMappings( asObj );
} else if ( cmd.equals( CMD_INVITE ) ) {
if ( ! forwardedPacket( asObj, bytes ) ) {
Intent intent = getIntentTo( P2PAction.GOT_INVITE );
@ -720,6 +748,86 @@ public class WiDirService extends XWService {
}
}
private static void addMappings( JSONObject packet )
{
synchronized( sUserMap ) {
try {
JSONArray array = new JSONArray();
for ( String mac : sUserMap.keySet() ) {
JSONObject map = new JSONObject()
.put( KEY_MAC, mac )
.put( KEY_NAME, sUserMap.get(mac) );
array.put( map );
}
packet.put( KEY_MAP, array );
} catch ( JSONException ex ) {
DbgUtils.logex( ex );
}
}
}
private static void readMappings( JSONObject asObj )
{
synchronized( sUserMap ) {
try {
JSONArray array = asObj.getJSONArray( KEY_MAP );
for ( int ii = 0; ii < array.length(); ++ii ) {
JSONObject map = array.getJSONObject( ii );
String name = map.getString( KEY_NAME );
String mac = map.getString( KEY_MAC );
sUserMap.put( mac, name );
}
} catch ( JSONException ex ) {
DbgUtils.logex( ex );
}
}
updateListeners();
}
private static void updateListeners()
{
DevSetListener[] listeners = null;
synchronized( s_devListeners ) {
if ( 0 < s_devListeners.size() ) {
listeners = new DevSetListener[s_devListeners.size()];
Iterator<DevSetListener> iter = s_devListeners.iterator();
for ( int ii = 0; ii < listeners.length; ++ii ) {
listeners[ii] = iter.next();
}
}
}
if ( null != listeners ) {
Map<String, String> macToName = copyUserMap();
macToName.remove( getMyMacAddress() );
for ( DevSetListener listener : listeners ) {
listener.setChanged( macToName );
}
}
}
private static Map<String, String> copyUserMap()
{
Map<String, String> macToName;
synchronized ( sUserMap ) {
macToName = new HashMap<String, String>(sUserMap);
}
return macToName;
}
private static String mapToString( Map<String, String> macToName )
{
String result = "";
Iterator<String> iter = macToName.keySet().iterator();
for ( int ii = 0; iter.hasNext(); ++ii ) {
String mac = iter.next();
result += String.format( "%d: %s=>%s; ", ii, mac,
macToName.get( mac ) );
}
return result;
}
private static boolean forwardedPacket( JSONObject asObj, byte[] bytes )
{
boolean forwarded = false;
@ -852,6 +960,9 @@ public class WiDirService extends XWService {
.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
sMacAddress = device.deviceAddress;
sDeviceName = device.deviceName;
synchronized( sUserMap ) {
sUserMap.put( sMacAddress, sDeviceName );
}
DbgUtils.logd( CLAZZ, "Got my MAC Address: %s and name: %s",
sMacAddress, sDeviceName );
@ -904,9 +1015,7 @@ public class WiDirService extends XWService {
// you'll want to create a client thread that connects to the group
// owner.
}
if ( BuildConfig.DEBUG ) {
getMgr().requestGroupInfo( sChannel, sGroupListener );
}
getMgr().requestGroupInfo( sChannel, sGroupListener );
} else {
Assert.fail();
}