implement deletion; save with new serialization util

Add new Utils methods that turn Serializable objects into B64-encoded
Strings, and vice versa. Use in place of existing code, and use anew to
store the array of DeviceID records. Implement the "Delete checked" button.
This commit is contained in:
Eric House 2017-07-23 17:31:59 -07:00
parent 7eb9458a78
commit a71d60db63
5 changed files with 92 additions and 77 deletions

View file

@ -39,10 +39,6 @@ import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet;
import org.eehouse.android.xw4.jni.XwJNI; import org.eehouse.android.xw4.jni.XwJNI;
import org.eehouse.android.xw4.loc.LocUtils; import org.eehouse.android.xw4.loc.LocUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -123,9 +119,8 @@ public class ConnStatusHandler {
private ConnStatusHandler() {} private ConnStatusHandler() {}
private static Map<CommsConnType,SuccessRecord[]> s_records = private static HashMap<CommsConnType,SuccessRecord[]> s_records =
new HashMap<CommsConnType,SuccessRecord[]>(); new HashMap<CommsConnType,SuccessRecord[]>();
private static Class s_lockObj = ConnStatusHandler.class;
private static boolean s_needsSave = false; private static boolean s_needsSave = false;
public static void setRect( int left, int top, int right, int bottom ) public static void setRect( int left, int top, int right, int bottom )
@ -172,7 +167,7 @@ public class ConnStatusHandler {
} else { } else {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
String tmp; String tmp;
synchronized( s_lockObj ) { synchronized( ConnStatusHandler.class ) {
sb.append( LocUtils.getString( context, sb.append( LocUtils.getString( context,
R.string.connstat_net_fmt, R.string.connstat_net_fmt,
connTypes.toString( context, true ))); connTypes.toString( context, true )));
@ -253,7 +248,7 @@ public class ConnStatusHandler {
cbacks = s_cbacks; cbacks = s_cbacks;
} }
synchronized( s_lockObj ) { synchronized( ConnStatusHandler.class ) {
SuccessRecord record = recordFor( connType, isIn ); SuccessRecord record = recordFor( connType, isIn );
record.update( success ); record.update( success );
} }
@ -288,7 +283,7 @@ public class ConnStatusHandler {
CommsConnTypeSet connTypes, boolean isSolo ) CommsConnTypeSet connTypes, boolean isSolo )
{ {
if ( !isSolo && null != s_rect ) { if ( !isSolo && null != s_rect ) {
synchronized( s_lockObj ) { synchronized( ConnStatusHandler.class ) {
Rect scratchR = new Rect( s_rect ); Rect scratchR = new Rect( s_rect );
int quarterHeight = scratchR.height() / 4; int quarterHeight = scratchR.height() / 4;
@ -351,20 +346,15 @@ public class ConnStatusHandler {
// @SuppressWarnings("unchecked") // @SuppressWarnings("unchecked")
public static void loadState( Context context ) public static void loadState( Context context )
{ {
synchronized( s_lockObj ) { synchronized( ConnStatusHandler.class ) {
s_records = null;
String as64 = XWPrefs.getPrefsString( context, String as64 = XWPrefs.getPrefsString( context,
R.string.key_connstat_data ); R.string.key_connstat_data );
if ( null != as64 && 0 < as64.length() ) { if ( null != as64 && 0 < as64.length() ) {
try { s_records = (HashMap<CommsConnType,SuccessRecord[]>)Utils.string64ToSerializable(as64);
byte[] bytes = Utils.base64Decode( as64 ); }
ObjectInputStream ois = if ( null == s_records ) {
new ObjectInputStream( new ByteArrayInputStream(bytes) ); s_records = new HashMap<CommsConnType,SuccessRecord[]>();
s_records =
(HashMap<CommsConnType,SuccessRecord[]>)ois.readObject();
} catch ( Exception ex ) {
Log.ex( TAG, ex );
s_records = new HashMap<CommsConnType,SuccessRecord[]>();
}
} }
} }
} }
@ -376,7 +366,7 @@ public class ConnStatusHandler {
doSave( context ); doSave( context );
} else { } else {
boolean savePending; boolean savePending;
synchronized( s_lockObj ) { synchronized( ConnStatusHandler.class ) {
savePending = s_needsSave; savePending = s_needsSave;
if ( !savePending ) { if ( !savePending ) {
s_needsSave = true; s_needsSave = true;
@ -400,7 +390,7 @@ public class ConnStatusHandler {
private static void showSuccess( ConnStatusCBacks cbcks, boolean isIn ) private static void showSuccess( ConnStatusCBacks cbcks, boolean isIn )
{ {
if ( null != cbcks ) { if ( null != cbcks ) {
synchronized( s_lockObj ) { synchronized( ConnStatusHandler.class ) {
if ( isIn && s_showSuccesses[SUCCESS_IN] ) { if ( isIn && s_showSuccesses[SUCCESS_IN] ) {
// do nothing // do nothing
} else if ( !isIn && s_showSuccesses[SUCCESS_OUT] ) { } else if ( !isIn && s_showSuccesses[SUCCESS_OUT] ) {
@ -413,7 +403,7 @@ public class ConnStatusHandler {
Runnable proc = new Runnable() { Runnable proc = new Runnable() {
public void run() { public void run() {
synchronized( s_lockObj ) { synchronized( ConnStatusHandler.class ) {
s_showSuccesses[index] = false; s_showSuccesses[index] = false;
invalidateParent(); invalidateParent();
} }
@ -468,21 +458,10 @@ public class ConnStatusHandler {
private static void doSave( Context context ) private static void doSave( Context context )
{ {
synchronized( s_lockObj ) { synchronized( ConnStatusHandler.class ) {
// DbgUtils.logf( "ConnStatusHandler:doSave() doing save" ); String as64 = Utils.serializableToString64( s_records );
ByteArrayOutputStream bas XWPrefs.setPrefsString( context, R.string.key_connstat_data,
= new ByteArrayOutputStream(); as64 );
try {
ObjectOutputStream out
= new ObjectOutputStream( bas );
out.writeObject( s_records );
out.flush();
String as64 = Utils.base64Encode( bas.toByteArray() );
XWPrefs.setPrefsString( context, R.string.key_connstat_data,
as64 );
} catch ( java.io.IOException ioe ) {
Log.ex( TAG, ioe );
}
s_needsSave = false; s_needsSave = false;
} }
} }

View file

@ -39,12 +39,7 @@ import android.widget.EditText;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.Spinner; import android.widget.Spinner;
import junit.framework.Assert; import java.io.Serializable;
import org.eehouse.android.xw4.DlgDelegate.Action;
import org.json.JSONArray;
import org.json.JSONObject;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -53,8 +48,16 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import org.json.JSONArray;
import org.json.JSONObject;
import junit.framework.Assert;
import org.eehouse.android.xw4.DlgDelegate.Action;
public class RelayInviteDelegate extends InviteDelegate { public class RelayInviteDelegate extends InviteDelegate {
private static final String TAG = RelayInviteDelegate.class.getSimpleName(); private static final String TAG = RelayInviteDelegate.class.getSimpleName();
private static final String RECS_KEY = "TAG" + "/recs";
private static int[] BUTTONIDS = { private static int[] BUTTONIDS = {
R.id.button_relay_add, R.id.button_relay_add,
@ -132,11 +135,10 @@ public class RelayInviteDelegate extends InviteDelegate {
showDialogFragment( DlgID.GET_NUMBER ); showDialogFragment( DlgID.GET_NUMBER );
break; break;
case R.id.button_clear: case R.id.button_clear:
Utils.notImpl( m_activity ); int count = getChecked().size();
// int count = getChecked().size(); String msg = getQuantityString( R.plurals.confirm_clear_relay_fmt,
// String msg = getQuantityString( R.plurals.confirm_clear_sms_fmt, count, count );
// count, count ); makeConfirmThenBuilder( msg, Action.CLEAR_ACTION ).show();
// makeConfirmThenBuilder( msg, Action.CLEAR_ACTION ).show();
break; break;
} }
} }
@ -430,25 +432,19 @@ public class RelayInviteDelegate extends InviteDelegate {
private void getSavedState() private void getSavedState()
{ {
String[] devIDs = XWPrefs.getRelayIDs( m_activity ); String dataString = DBUtils.getStringFor( m_activity, RECS_KEY, null );
if ( null == dataString ) {
m_devIDRecs = new ArrayList<DevIDRec>(devIDs.length); m_devIDRecs = new ArrayList<DevIDRec>();
for ( String devID : devIDs ) { } else {
DevIDRec rec = new DevIDRec( "me", devID ); m_devIDRecs = (ArrayList<DevIDRec>)Utils
m_devIDRecs.add( rec ); .string64ToSerializable( dataString );
} }
} }
private void saveAndRebuild() private void saveAndRebuild()
{ {
String[] devIDs = new String[m_devIDRecs.size()]; String as64 = Utils.serializableToString64( m_devIDRecs );
Iterator<DevIDRec> iter = m_devIDRecs.iterator(); DBUtils.setStringFor( m_activity, RECS_KEY, as64 );
for ( int ii = 0; iter.hasNext(); ++ii ) {
DevIDRec rec = iter.next();
devIDs[ii] = rec.m_devID;
}
XWPrefs.setRelayIDs( m_activity, devIDs );
rebuildList( false ); rebuildList( false );
} }
@ -467,6 +463,16 @@ public class RelayInviteDelegate extends InviteDelegate {
private void clearSelectedImpl() private void clearSelectedImpl()
{ {
Set<InviterItem> checked = getChecked();
Iterator<DevIDRec> iter = m_devIDRecs.iterator();
for ( ; iter.hasNext(); ) {
if ( checked.contains( iter.next() ) ) {
iter.remove();
}
}
clearChecked();
saveAndRebuild();
// int count = m_adapter.getCount(); // int count = m_adapter.getCount();
// for ( int ii = count - 1; ii >= 0; --ii ) { // for ( int ii = count - 1; ii >= 0; --ii ) {
// if ( m_devIDRecs.get( ii ).m_isChecked ) { // if ( m_devIDRecs.get( ii ).m_isChecked ) {
@ -476,7 +482,7 @@ public class RelayInviteDelegate extends InviteDelegate {
// saveAndRebuild(); // saveAndRebuild();
} }
private class DevIDRec implements InviterItem { private static class DevIDRec implements InviterItem, Serializable {
public String m_devID; public String m_devID;
public String m_opponent; public String m_opponent;
public int m_nPlayers; public int m_nPlayers;

View file

@ -55,7 +55,12 @@ import android.widget.Toast;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -497,6 +502,37 @@ public class Utils {
return Base64.decode( in, Base64.NO_WRAP ); return Base64.decode( in, Base64.NO_WRAP );
} }
public static Object string64ToSerializable( String str64 )
{
Object result = null;
byte[] bytes = base64Decode( str64 );
try {
ObjectInputStream ois =
new ObjectInputStream( new ByteArrayInputStream(bytes) );
result = ois.readObject();
} catch ( Exception ex ) {
Log.ex( TAG, ex );
Assert.assertFalse( BuildConfig.DEBUG );
}
return result;
}
public static String serializableToString64( Serializable obj )
{
String result = null;
ByteArrayOutputStream bas = new ByteArrayOutputStream();
try {
ObjectOutputStream out = new ObjectOutputStream( bas );
out.writeObject( obj );
out.flush();
result = base64Encode( bas.toByteArray() );
} catch ( Exception ex ) {
Log.ex( TAG, ex );
Assert.assertFalse( BuildConfig.DEBUG );
}
return result;
}
private static void setFirstBootStatics( Context context ) private static void setFirstBootStatics( Context context )
{ {
if ( null == s_isFirstBootThisVersion ) { if ( null == s_isFirstBootThisVersion ) {

View file

@ -278,17 +278,6 @@ public class XWPrefs {
return obj; return obj;
} }
// Used by RelayInviteDelegate.java
public static void setRelayIDs( Context context, String[] names )
{
setPrefsStringArray( context, R.string.key_relay_ids, names );
}
public static String[] getRelayIDs( Context context )
{
return getPrefsStringArray( context, R.string.key_relay_ids );
}
public static void setBTAddresses( Context context, String[] addrs ) public static void setBTAddresses( Context context, String[] addrs )
{ {
setPrefsStringArray( context, R.string.key_bt_addrs, addrs ); setPrefsStringArray( context, R.string.key_bt_addrs, addrs );

View file

@ -1932,8 +1932,13 @@
<item quantity="other">Are you sure you want to delete the <item quantity="other">Are you sure you want to delete the
%1$d checked phone numbers?</item> %1$d checked phone numbers?</item>
</plurals> </plurals>
<string name="confirm_clear_relay">Are you sure you want to delete the <plurals name="confirm_clear_relay_fmt">
checked device[s]?</string> <item quantity="one">Are you sure you want to delete the checked
RelayID record?</item>
<item quantity="other">Are you sure you want to delete the
%1$d checked RelayID records?</item>
</plurals>
<!-- --> <!-- -->
<string name="summary_conn_sms_fmt">Game in play with %1$s</string> <string name="summary_conn_sms_fmt">Game in play with %1$s</string>
<!-- --> <!-- -->