From 1aa701ceeeaa4e2a2ff4bfa36844d42f2fa8b88e Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Tue, 30 Apr 2013 17:24:04 +0100 Subject: [PATCH] Save and restore UI state when screen is rotated. Fixes issue #3611920, but keep the issue open because more activities will be added. --- .../sf/briar/android/HomeScreenActivity.java | 1 + .../net/sf/briar/android/SetupActivity.java | 3 ++ .../android/blogs/ConfigureBlogActivity.java | 9 ++-- .../android/blogs/CreateBlogActivity.java | 3 ++ .../android/blogs/WriteBlogPostActivity.java | 44 ++++++++++++++++++- .../groups/ConfigureGroupActivity.java | 9 ++-- .../android/groups/CreateGroupActivity.java | 3 ++ .../groups/WriteGroupPostActivity.java | 44 ++++++++++++++++++- .../identity/CreateIdentityActivity.java | 1 + .../invitation/AddContactActivity.java | 4 +- .../android/invitation/CodeEntryWidget.java | 1 + .../messages/WritePrivateMessageActivity.java | 19 +++++++- 12 files changed, 128 insertions(+), 13 deletions(-) diff --git a/briar-android/src/net/sf/briar/android/HomeScreenActivity.java b/briar-android/src/net/sf/briar/android/HomeScreenActivity.java index 2798b2693e..02ae13fcc5 100644 --- a/briar-android/src/net/sf/briar/android/HomeScreenActivity.java +++ b/briar-android/src/net/sf/briar/android/HomeScreenActivity.java @@ -203,6 +203,7 @@ public class HomeScreenActivity extends RoboActivity { layout.addView(enterPassword); final EditText passwordEntry = new EditText(this); + passwordEntry.setId(1); passwordEntry.setMaxLines(1); int inputType = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD; passwordEntry.setInputType(inputType); diff --git a/briar-android/src/net/sf/briar/android/SetupActivity.java b/briar-android/src/net/sf/briar/android/SetupActivity.java index f54e4e6746..e272774b7b 100644 --- a/briar-android/src/net/sf/briar/android/SetupActivity.java +++ b/briar-android/src/net/sf/briar/android/SetupActivity.java @@ -79,6 +79,7 @@ public class SetupActivity extends RoboActivity implements OnClickListener { enableOrDisableContinueButton(); } }; + nicknameEntry.setId(1); nicknameEntry.setMaxLines(1); int inputType = TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_WORDS; nicknameEntry.setInputType(inputType); @@ -98,6 +99,7 @@ public class SetupActivity extends RoboActivity implements OnClickListener { enableOrDisableContinueButton(); } }; + passwordEntry.setId(2); passwordEntry.setMaxLines(1); inputType = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD; passwordEntry.setInputType(inputType); @@ -117,6 +119,7 @@ public class SetupActivity extends RoboActivity implements OnClickListener { enableOrDisableContinueButton(); } }; + passwordConfirmation.setId(3); passwordConfirmation.setMaxLines(1); inputType = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD; passwordConfirmation.setInputType(inputType); diff --git a/briar-android/src/net/sf/briar/android/blogs/ConfigureBlogActivity.java b/briar-android/src/net/sf/briar/android/blogs/ConfigureBlogActivity.java index 420eebf2bc..3c5699330b 100644 --- a/briar-android/src/net/sf/briar/android/blogs/ConfigureBlogActivity.java +++ b/briar-android/src/net/sf/briar/android/blogs/ConfigureBlogActivity.java @@ -87,6 +87,7 @@ SelectContactsDialog.Listener { layout.setGravity(CENTER_HORIZONTAL); subscribeCheckBox = new CheckBox(this); + subscribeCheckBox.setId(1); subscribeCheckBox.setText(R.string.subscribe_to_this_blog); subscribeCheckBox.setChecked(subscribed); subscribeCheckBox.setOnClickListener(this); @@ -96,21 +97,21 @@ SelectContactsDialog.Listener { radioGroup.setOrientation(VERTICAL); visibleToAll = new RadioButton(this); - visibleToAll.setId(1); + visibleToAll.setId(2); visibleToAll.setText(R.string.blog_visible_to_all); visibleToAll.setEnabled(subscribed); visibleToAll.setOnClickListener(this); radioGroup.addView(visibleToAll); visibleToSome = new RadioButton(this); - visibleToSome.setId(2); + visibleToSome.setId(3); visibleToSome.setText(R.string.blog_visible_to_some); visibleToSome.setEnabled(subscribed); visibleToSome.setOnClickListener(this); radioGroup.addView(visibleToSome); - if(!subscribed || all) radioGroup.check(1); - else radioGroup.check(2); + if(!subscribed || all) radioGroup.check(visibleToAll.getId()); + else radioGroup.check(visibleToSome.getId()); layout.addView(radioGroup); doneButton = new Button(this); diff --git a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java b/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java index fe7d99ae64..1d3f5deb46 100644 --- a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java +++ b/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java @@ -99,6 +99,7 @@ SelectContactsDialog.Listener { enableOrDisableCreateButton(); } }; + nameEntry.setId(1); nameEntry.setMaxLines(1); nameEntry.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES); nameEntry.setOnEditorActionListener(this); @@ -108,11 +109,13 @@ SelectContactsDialog.Listener { radioGroup.setOrientation(VERTICAL); visibleToAll = new RadioButton(this); + visibleToAll.setId(2); visibleToAll.setText(R.string.blog_visible_to_all); visibleToAll.setOnClickListener(this); radioGroup.addView(visibleToAll); visibleToSome = new RadioButton(this); + visibleToSome.setId(3); visibleToSome.setText(R.string.blog_visible_to_some); visibleToSome.setOnClickListener(this); radioGroup.addView(visibleToSome); diff --git a/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java b/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java index e8242ba17c..de0bc88d54 100644 --- a/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java +++ b/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java @@ -24,6 +24,7 @@ import net.sf.briar.android.identity.LocalAuthorItem; import net.sf.briar.android.identity.LocalAuthorItemComparator; import net.sf.briar.android.identity.LocalAuthorSpinnerAdapter; import net.sf.briar.android.widgets.HorizontalSpace; +import net.sf.briar.api.AuthorId; import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.DatabaseUiExecutor; import net.sf.briar.api.crypto.CryptoComponent; @@ -67,13 +68,14 @@ implements OnItemSelectedListener, OnClickListener { private Spinner fromSpinner = null, toSpinner = null; private ImageButton sendButton = null; private EditText content = null; + private AuthorId localAuthorId = null; + private GroupId localGroupId = null; // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; private volatile LocalAuthor localAuthor = null; private volatile LocalGroup localGroup = null; - private volatile GroupId localGroupId = null; private volatile MessageId parentId = null; @Override @@ -86,6 +88,13 @@ implements OnItemSelectedListener, OnClickListener { b = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); if(b != null) parentId = new MessageId(b); + if(state != null) { + b = state.getByteArray("net.sf.briar.LOCAL_AUTHOR_ID"); + if(b != null) localAuthorId = new AuthorId(b); + b = state.getByteArray("net.sf.briar.LOCAL_GROUP_ID"); + if(b != null) localGroupId = new GroupId(b); + } + LinearLayout layout = new LinearLayout(this); layout.setLayoutParams(MATCH_WRAP); layout.setOrientation(VERTICAL); @@ -136,6 +145,7 @@ implements OnItemSelectedListener, OnClickListener { layout.addView(header); content = new EditText(this); + content.setId(1); int inputType = TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | TYPE_TEXT_FLAG_CAP_SENTENCES; content.setInputType(inputType); @@ -187,6 +197,17 @@ implements OnItemSelectedListener, OnClickListener { fromAdapter.add(new LocalAuthorItem(a)); fromAdapter.sort(LocalAuthorItemComparator.INSTANCE); fromAdapter.notifyDataSetChanged(); + int count = fromAdapter.getCount(); + for(int i = 0; i < count; i++) { + LocalAuthorItem item = fromAdapter.getItem(i); + if(item == LocalAuthorItem.ANONYMOUS) continue; + if(item == LocalAuthorItem.NEW) continue; + if(item.getLocalAuthor().getId().equals(localAuthorId)) { + localAuthor = item.getLocalAuthor(); + fromSpinner.setSelection(i); + break; + } + } } }); } @@ -226,6 +247,7 @@ implements OnItemSelectedListener, OnClickListener { LocalGroupItem item = toAdapter.getItem(i); if(item == LocalGroupItem.NEW) continue; if(item.getLocalGroup().getId().equals(localGroupId)) { + localGroup = item.getLocalGroup(); toSpinner.setSelection(i); break; } @@ -234,6 +256,19 @@ implements OnItemSelectedListener, OnClickListener { }); } + @Override + public void onSaveInstanceState(Bundle state) { + super.onSaveInstanceState(state); + if(localAuthorId != null) { + byte[] b = localAuthorId.getBytes(); + state.putByteArray("net.sf.briar.LOCAL_AUTHOR_ID", b); + } + if(localGroupId != null) { + byte[] b = localGroupId.getBytes(); + state.putByteArray("net.sf.briar.LOCAL_GROUP_ID", b); + } + } + @Override public void onDestroy() { super.onDestroy(); @@ -246,15 +281,20 @@ implements OnItemSelectedListener, OnClickListener { LocalAuthorItem item = fromAdapter.getItem(position); if(item == LocalAuthorItem.ANONYMOUS) { localAuthor = null; + localAuthorId = null; } else if(item == LocalAuthorItem.NEW) { localAuthor = null; + localAuthorId = null; startActivity(new Intent(this, CreateIdentityActivity.class)); } else { localAuthor = item.getLocalAuthor(); + localAuthorId = localAuthor.getId(); } } else if(parent == toSpinner) { LocalGroupItem item = toAdapter.getItem(position); if(item == LocalGroupItem.NEW) { + localGroup = null; + localGroupId = null; startActivity(new Intent(this, CreateBlogActivity.class)); } else { localGroup = item.getLocalGroup(); @@ -267,6 +307,7 @@ implements OnItemSelectedListener, OnClickListener { public void onNothingSelected(AdapterView<?> parent) { if(parent == fromSpinner) { localAuthor = null; + localAuthorId = null; } else if(parent == toSpinner) { localGroup = null; localGroupId = null; @@ -287,6 +328,7 @@ implements OnItemSelectedListener, OnClickListener { finish(); } + // FIXME: This should happen on a CryptoExecutor thread private Message createMessage(byte[] body) throws IOException, GeneralSecurityException { KeyParser keyParser = crypto.getSignatureKeyParser(); diff --git a/briar-android/src/net/sf/briar/android/groups/ConfigureGroupActivity.java b/briar-android/src/net/sf/briar/android/groups/ConfigureGroupActivity.java index d432b28334..6ba4670e75 100644 --- a/briar-android/src/net/sf/briar/android/groups/ConfigureGroupActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/ConfigureGroupActivity.java @@ -85,6 +85,7 @@ SelectContactsDialog.Listener { layout.setGravity(CENTER_HORIZONTAL); subscribeCheckBox = new CheckBox(this); + subscribeCheckBox.setId(1); subscribeCheckBox.setText(R.string.subscribe_to_this_group); subscribeCheckBox.setChecked(subscribed); subscribeCheckBox.setOnClickListener(this); @@ -94,21 +95,21 @@ SelectContactsDialog.Listener { radioGroup.setOrientation(VERTICAL); visibleToAll = new RadioButton(this); - visibleToAll.setId(1); + visibleToAll.setId(2); visibleToAll.setText(R.string.group_visible_to_all); visibleToAll.setEnabled(subscribed); visibleToAll.setOnClickListener(this); radioGroup.addView(visibleToAll); visibleToSome = new RadioButton(this); - visibleToSome.setId(2); + visibleToSome.setId(3); visibleToSome.setText(R.string.group_visible_to_some); visibleToSome.setEnabled(subscribed); visibleToSome.setOnClickListener(this); radioGroup.addView(visibleToSome); - if(!subscribed || all) radioGroup.check(1); - else radioGroup.check(2); + if(!subscribed || all) radioGroup.check(visibleToAll.getId()); + else radioGroup.check(visibleToSome.getId()); layout.addView(radioGroup); doneButton = new Button(this); diff --git a/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java b/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java index 04bd359254..7793a6a8a4 100644 --- a/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/CreateGroupActivity.java @@ -94,6 +94,7 @@ SelectContactsDialog.Listener { enableOrDisableCreateButton(); } }; + nameEntry.setId(1); nameEntry.setMaxLines(1); nameEntry.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES); nameEntry.setOnEditorActionListener(this); @@ -103,11 +104,13 @@ SelectContactsDialog.Listener { radioGroup.setOrientation(VERTICAL); visibleToAll = new RadioButton(this); + visibleToAll.setId(2); visibleToAll.setText(R.string.blog_visible_to_all); visibleToAll.setOnClickListener(this); radioGroup.addView(visibleToAll); visibleToSome = new RadioButton(this); + visibleToSome.setId(3); visibleToSome.setText(R.string.blog_visible_to_some); visibleToSome.setOnClickListener(this); radioGroup.addView(visibleToSome); diff --git a/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java b/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java index cb05d3266c..779857e43e 100644 --- a/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/WriteGroupPostActivity.java @@ -27,6 +27,7 @@ import net.sf.briar.android.identity.LocalAuthorItem; import net.sf.briar.android.identity.LocalAuthorItemComparator; import net.sf.briar.android.identity.LocalAuthorSpinnerAdapter; import net.sf.briar.android.widgets.HorizontalSpace; +import net.sf.briar.api.AuthorId; import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.DatabaseUiExecutor; import net.sf.briar.api.crypto.CryptoComponent; @@ -70,13 +71,14 @@ implements OnItemSelectedListener, OnClickListener { private Spinner fromSpinner = null, toSpinner = null; private ImageButton sendButton = null; private EditText content = null; + private AuthorId localAuthorId = null; + private GroupId groupId = null; // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; private volatile LocalAuthor localAuthor = null; private volatile Group group = null; - private volatile GroupId groupId = null; private volatile MessageId parentId = null; @Override @@ -89,6 +91,13 @@ implements OnItemSelectedListener, OnClickListener { b = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); if(b != null) parentId = new MessageId(b); + if(state != null) { + b = state.getByteArray("net.sf.briar.LOCAL_AUTHOR_ID"); + if(b != null) localAuthorId = new AuthorId(b); + b = state.getByteArray("net.sf.briar.GROUP_ID"); + if(b != null) groupId = new GroupId(b); + } + LinearLayout layout = new LinearLayout(this); layout.setLayoutParams(MATCH_WRAP); layout.setOrientation(VERTICAL); @@ -139,6 +148,7 @@ implements OnItemSelectedListener, OnClickListener { layout.addView(header); content = new EditText(this); + content.setId(1); int inputType = TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | TYPE_TEXT_FLAG_CAP_SENTENCES; content.setInputType(inputType); @@ -190,6 +200,17 @@ implements OnItemSelectedListener, OnClickListener { fromAdapter.add(new LocalAuthorItem(a)); fromAdapter.sort(LocalAuthorItemComparator.INSTANCE); fromAdapter.notifyDataSetChanged(); + int count = fromAdapter.getCount(); + for(int i = 0; i < count; i++) { + LocalAuthorItem item = fromAdapter.getItem(i); + if(item == LocalAuthorItem.ANONYMOUS) continue; + if(item == LocalAuthorItem.NEW) continue; + if(item.getLocalAuthor().getId().equals(localAuthorId)) { + localAuthor = item.getLocalAuthor(); + fromSpinner.setSelection(i); + break; + } + } } }); } @@ -231,6 +252,7 @@ implements OnItemSelectedListener, OnClickListener { GroupItem g = toAdapter.getItem(i); if(g == GroupItem.NEW) continue; if(g.getGroup().getId().equals(groupId)) { + group = g.getGroup(); toSpinner.setSelection(i); break; } @@ -239,6 +261,19 @@ implements OnItemSelectedListener, OnClickListener { }); } + @Override + public void onSaveInstanceState(Bundle state) { + super.onSaveInstanceState(state); + if(localAuthorId != null) { + byte[] b = localAuthorId.getBytes(); + state.putByteArray("net.sf.briar.LOCAL_AUTHOR_ID", b); + } + if(groupId != null) { + byte[] b = groupId.getBytes(); + state.putByteArray("net.sf.briar.GROUP_ID", b); + } + } + @Override public void onDestroy() { super.onDestroy(); @@ -251,15 +286,20 @@ implements OnItemSelectedListener, OnClickListener { LocalAuthorItem item = fromAdapter.getItem(position); if(item == LocalAuthorItem.ANONYMOUS) { localAuthor = null; + localAuthorId = null; } else if(item == LocalAuthorItem.NEW) { localAuthor = null; + localAuthorId = null; startActivity(new Intent(this, CreateIdentityActivity.class)); } else { localAuthor = item.getLocalAuthor(); + localAuthorId = localAuthor.getId(); } } else if(parent == toSpinner) { GroupItem item = toAdapter.getItem(position); if(item == GroupItem.NEW) { + group = null; + groupId = null; startActivity(new Intent(this, CreateGroupActivity.class)); } else { group = item.getGroup(); @@ -272,6 +312,7 @@ implements OnItemSelectedListener, OnClickListener { public void onNothingSelected(AdapterView<?> parent) { if(parent == fromSpinner) { localAuthor = null; + localAuthorId = null; } else if(parent == toSpinner) { group = null; groupId = null; @@ -292,6 +333,7 @@ implements OnItemSelectedListener, OnClickListener { finish(); } + // FIXME: This should happen on a CryptoExecutor thread private Message createMessage(byte[] body) throws IOException, GeneralSecurityException { if(localAuthor == null) { diff --git a/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java b/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java index eeadc22e68..9a331a0381 100644 --- a/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java +++ b/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java @@ -88,6 +88,7 @@ implements OnEditorActionListener, OnClickListener { createButton.setEnabled(getText().length() > 0); } }; + nicknameEntry.setId(1); nicknameEntry.setMaxLines(1); int inputType = TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_WORDS; nicknameEntry.setInputType(inputType); diff --git a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java index 43378046d1..1ade68d616 100644 --- a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java +++ b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java @@ -174,8 +174,8 @@ implements InvitationListener { public void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); if(localAuthorId != null) { - state.putByteArray("net.sf.briar.LOCAL_AUTHOR_ID", - localAuthorId.getBytes()); + byte[] b = localAuthorId.getBytes(); + state.putByteArray("net.sf.briar.LOCAL_AUTHOR_ID", b); } state.putInt("net.sf.briar.LOCAL_CODE", localInvitationCode); state.putInt("net.sf.briar.REMOTE_CODE", remoteInvitationCode); diff --git a/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java b/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java index 657cb5c3d9..d9b2901e91 100644 --- a/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java +++ b/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java @@ -54,6 +54,7 @@ implements OnEditorActionListener, OnClickListener { continueButton.setEnabled(getText().length() == 6); } }; + codeEntry.setId(1); codeEntry.setTextSize(26); codeEntry.setOnEditorActionListener(this); codeEntry.setMinEms(5); diff --git a/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java b/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java index 734652ef9f..a948891e21 100644 --- a/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java @@ -83,6 +83,11 @@ implements OnItemSelectedListener, OnClickListener { byte[] b = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); if(b != null) parentId = new MessageId(b); + if(state != null) { + id = state.getInt("net.sf.briar.CONTACT_ID", -1); + if(id != -1) contactId = new ContactId(id); + } + LinearLayout layout = new LinearLayout(this); layout.setLayoutParams(MATCH_WRAP); layout.setOrientation(VERTICAL); @@ -127,6 +132,7 @@ implements OnItemSelectedListener, OnClickListener { layout.addView(header); content = new EditText(this); + content.setId(1); int inputType = TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | TYPE_TEXT_FLAG_CAP_SENTENCES; content.setInputType(inputType); @@ -188,6 +194,13 @@ implements OnItemSelectedListener, OnClickListener { }); } + @Override + public void onSaveInstanceState(Bundle state) { + super.onSaveInstanceState(state); + if(contactId != null) + state.putInt("net.sf.briar.CONTACT_ID", contactId.getInt()); + } + @Override public void onDestroy() { super.onDestroy(); @@ -198,12 +211,16 @@ implements OnItemSelectedListener, OnClickListener { long id) { ContactItem item = adapter.getItem(position); if(item == ContactItem.NEW) { + contactId = null; + localAuthor = null; startActivity(new Intent(this, AddContactActivity.class)); } else { Contact c = item.getContact(); - loadLocalAuthor(c.getLocalAuthorId()); contactId = c.getId(); + localAuthor = null; + loadLocalAuthor(c.getLocalAuthorId()); } + sendButton.setEnabled(false); } private void loadLocalAuthor(final AuthorId a) { -- GitLab