From b5c0e4478c06cbc8c676df75ac69760473136293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 22 Sep 2013 21:50:46 +0200 Subject: [PATCH] Fix file import, commitAllowingStateLoss() was he answer to fragment crashes, PS: I hate fragment lifecycles... --- .../keychain/ui/ImportKeysActivity.java | 121 ++++++++++-------- .../keychain/ui/ImportKeysFileFragment.java | 9 +- .../keychain/ui/ImportKeysListFragment.java | 46 ++++++- .../ui/adapter/ImportKeysAdapter.java | 4 +- .../ui/adapter/ImportKeysListLoader.java | 29 +---- 5 files changed, 122 insertions(+), 87 deletions(-) diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index ecccd64d0..2c7a3ea45 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -92,6 +92,65 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa getSupportActionBar().setListNavigationCallbacks(list, this); getSupportActionBar().setDisplayShowTitleEnabled(false); + handleActions(savedInstanceState, getIntent()); + } + + protected void handleActions(Bundle savedInstanceState, Intent intent) { + String action = intent.getAction(); + Bundle extras = intent.getExtras(); + + if (extras == null) { + extras = new Bundle(); + } + + /** + * Android Standard Actions + */ + if (Intent.ACTION_VIEW.equals(action)) { + // Android's Action when opening file associated to Keychain (see AndroidManifest.xml) + // override action to delegate it to Keychain's ACTION_IMPORT_KEY + action = ACTION_IMPORT_KEY; + } + + /** + * Keychain's own Actions + */ + if (ACTION_IMPORT_KEY.equals(action)) { + if ("file".equals(intent.getScheme()) && intent.getDataString() != null) { + String importFilename = intent.getData().getPath(); + + // display selected filename + getSupportActionBar().setSelectedNavigationItem(0); + Bundle args = new Bundle(); + args.putString(ImportKeysFileFragment.ARG_PATH, importFilename); + loadFragment(ImportKeysFileFragment.class, args, mNavigationStrings[0]); + + // directly load data + startListFragment(savedInstanceState, null, importFilename); + } else if (extras.containsKey(EXTRA_KEY_BYTES)) { + byte[] importData = intent.getByteArrayExtra(EXTRA_KEY_BYTES); + + // directly load data + startListFragment(savedInstanceState, importData, null); + } + } else { + // Internal actions + startListFragment(savedInstanceState, null, null); + + if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) { + getSupportActionBar().setSelectedNavigationItem(0); + loadFragment(ImportKeysFileFragment.class, null, mNavigationStrings[0]); + } else if (ACTION_IMPORT_KEY_FROM_QR_CODE.equals(action)) { + getSupportActionBar().setSelectedNavigationItem(2); + loadFragment(ImportKeysQrCodeFragment.class, null, mNavigationStrings[2]); + } else if (ACTION_IMPORT_KEY_FROM_NFC.equals(action)) { + getSupportActionBar().setSelectedNavigationItem(3); + loadFragment(ImportKeysNFCFragment.class, null, mNavigationStrings[3]); + } + } + } + + private void startListFragment(Bundle savedInstanceState, byte[] bytes, String filename) { // Check that the activity is using the layout version with // the fragment_container FrameLayout if (findViewById(R.id.import_keys_list_container) != null) { @@ -104,16 +163,15 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa } // Create an instance of the fragment - mListFragment = ImportKeysListFragment.newInstance(); + mListFragment = ImportKeysListFragment.newInstance(bytes, filename); // Add the fragment to the 'fragment_container' FrameLayout getSupportFragmentManager().beginTransaction() - .replace(R.id.import_keys_list_container, mListFragment).commit(); + .replace(R.id.import_keys_list_container, mListFragment) + .commitAllowingStateLoss(); // do it immediately! getSupportFragmentManager().executePendingTransactions(); } - - handleActions(getIntent()); } @Override @@ -151,7 +209,11 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa } public void loadCallback(byte[] importData, String importFilename) { - mListFragment.load(importData, importFilename); + if (mListFragment == null) { + startListFragment(null, importData, importFilename); + } else { + mListFragment.loadNew(importData, importFilename); + } } @Override @@ -171,55 +233,6 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa } } - protected void handleActions(Intent intent) { - String action = intent.getAction(); - Bundle extras = intent.getExtras(); - - if (extras == null) { - extras = new Bundle(); - } - - /** - * Android Standard Actions - */ - if (Intent.ACTION_VIEW.equals(action)) { - // Android's Action when opening file associated to Keychain (see AndroidManifest.xml) - // override action to delegate it to Keychain's ACTION_IMPORT_KEY - action = ACTION_IMPORT_KEY; - } - - /** - * Keychain's own Actions - */ - if (ACTION_IMPORT_KEY.equals(action)) { - if ("file".equals(intent.getScheme()) && intent.getDataString() != null) { - String importFilename = intent.getData().getPath(); - - // display selected filename - getSupportActionBar().setSelectedNavigationItem(0); - Bundle args = new Bundle(); - args.putString(ImportKeysFileFragment.ARG_PATH, importFilename); - loadFragment(ImportKeysFileFragment.class, args, mNavigationStrings[0]); - - // directly load data - loadCallback(null, importFilename); - } else if (extras.containsKey(EXTRA_KEY_BYTES)) { - byte[] importData = intent.getByteArrayExtra(EXTRA_KEY_BYTES); - loadCallback(importData, null); - } - // Internal actions: - } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) { - getSupportActionBar().setSelectedNavigationItem(0); - loadFragment(ImportKeysFileFragment.class, null, mNavigationStrings[0]); - } else if (ACTION_IMPORT_KEY_FROM_QR_CODE.equals(action)) { - getSupportActionBar().setSelectedNavigationItem(2); - loadFragment(ImportKeysQrCodeFragment.class, null, mNavigationStrings[2]); - } else if (ACTION_IMPORT_KEY_FROM_NFC.equals(action)) { - getSupportActionBar().setSelectedNavigationItem(3); - loadFragment(ImportKeysNFCFragment.class, null, mNavigationStrings[3]); - } - } - // private void importAndSignOld(final long keyId, final String expectedFingerprint) { // if (expectedFingerprint != null && expectedFingerprint.length() > 0) { // diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java index 7d77a7b09..fbca9013b 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java @@ -95,18 +95,19 @@ public class ImportKeysFileFragment extends Fragment { switch (requestCode) { case Id.request.filename: { if (resultCode == Activity.RESULT_OK && data != null) { + String path = null; try { - String path = data.getData().getPath(); + path = data.getData().getPath(); Log.d(Constants.TAG, "path=" + path); // set filename to edittext mFilename.setText(path); - - // load data - mImportActivity.loadCallback(null, path); } catch (NullPointerException e) { Log.e(Constants.TAG, "Nullpointer while retrieving path!", e); } + + // load data + mImportActivity.loadCallback(null, path); } break; diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index 1925a5509..fcd79a9be 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -17,6 +17,9 @@ package org.sufficientlysecure.keychain.ui; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.util.List; import org.sufficientlysecure.keychain.Constants; @@ -24,6 +27,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader; +import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import android.app.Activity; @@ -37,6 +41,8 @@ import com.actionbarsherlock.app.SherlockListFragment; public class ImportKeysListFragment extends SherlockListFragment implements LoaderManager.LoaderCallbacks> { + private static final String ARG_FILENAME = "filename"; + private static final String ARG_BYTES = "bytes"; private Activity mActivity; private ImportKeysAdapter mAdapter; @@ -59,9 +65,15 @@ public class ImportKeysListFragment extends SherlockListFragment implements /** * Creates new instance of this fragment */ - public static ImportKeysListFragment newInstance() { + public static ImportKeysListFragment newInstance(byte[] bytes, String filename) { ImportKeysListFragment frag = new ImportKeysListFragment(); + Bundle args = new Bundle(); + args.putByteArray(ARG_BYTES, bytes); + args.putString(ARG_FILENAME, filename); + + frag.setArguments(args); + return frag; } @@ -74,15 +86,17 @@ public class ImportKeysListFragment extends SherlockListFragment implements mActivity = getActivity(); - // register long press context menu - registerForContextMenu(getListView()); + if (getArguments() != null) { + mImportFilename = getArguments().getString(ARG_FILENAME); + mKeyBytes = getArguments().getByteArray(ARG_BYTES); + } // Give some text to display if there is no data. In a real // application this would come from a resource. setEmptyText(mActivity.getString(R.string.error_nothingImport)); // Create an empty adapter we will use to display the loaded data. - mAdapter = new ImportKeysAdapter(getActivity()); + mAdapter = new ImportKeysAdapter(mActivity); setListAdapter(mAdapter); // Start out with a progress indicator. @@ -90,6 +104,7 @@ public class ImportKeysListFragment extends SherlockListFragment implements // Prepare the loader. Either re-connect with an existing one, // or start a new one. + // give arguments to onCreateLoader() getLoaderManager().initLoader(0, null, this); } @@ -105,14 +120,33 @@ public class ImportKeysListFragment extends SherlockListFragment implements mAdapter.notifyDataSetChanged(); } - public void load(byte[] importData, String importFilename) { + public void loadNew(byte[] importData, String importFilename) { this.mKeyBytes = importData; this.mImportFilename = importFilename; + + getLoaderManager().restartLoader(0, null, this); } @Override public Loader> onCreateLoader(int id, Bundle args) { - return new ImportKeysListLoader(mActivity, mKeyBytes, mImportFilename); + InputData inputData = getInputData(mKeyBytes, mImportFilename); + return new ImportKeysListLoader(mActivity, inputData); + } + + private InputData getInputData(byte[] importBytes, String importFilename) { + InputData inputData = null; + if (importBytes != null) { + inputData = new InputData(new ByteArrayInputStream(importBytes), importBytes.length); + } else if (importFilename != null) { + try { + inputData = new InputData(new FileInputStream(importFilename), + importFilename.length()); + } catch (FileNotFoundException e) { + Log.e(Constants.TAG, "Failed to init FileInputStream!", e); + } + } + + return inputData; } @Override diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 26416057c..3d6435cf3 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -51,6 +51,9 @@ public class ImportKeysAdapter extends ArrayAdapter { public void setData(List data) { clear(); if (data != null) { + this.data = data; + + // add data to extended ArrayAdapter if (Build.VERSION.SDK_INT >= 11) { addAll(data); } else { @@ -58,7 +61,6 @@ public class ImportKeysAdapter extends ArrayAdapter { add(entry); } } - this.data = data; } } diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java index 2e5239a93..00ad8c957 100644 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java +++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -18,9 +18,6 @@ package org.sufficientlysecure.keychain.ui.adapter; import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; @@ -39,36 +36,24 @@ import android.support.v4.content.AsyncTaskLoader; public class ImportKeysListLoader extends AsyncTaskLoader> { Context mContext; + InputData mInputData; + ArrayList data = new ArrayList(); - byte[] mKeyringBytes; - String mImportFilename; - - public ImportKeysListLoader(Context context, byte[] keyringBytes, String importFilename) { + public ImportKeysListLoader(Context context, InputData inputData) { super(context); this.mContext = context; - this.mKeyringBytes = keyringBytes; - this.mImportFilename = importFilename; + this.mInputData = inputData; } @Override public List loadInBackground() { - InputData inputData = null; - if (mKeyringBytes != null) { - inputData = new InputData(new ByteArrayInputStream(mKeyringBytes), mKeyringBytes.length); - } else if (mImportFilename != null) { - try { - inputData = new InputData(new FileInputStream(mImportFilename), - mImportFilename.length()); - } catch (FileNotFoundException e) { - Log.e(Constants.TAG, "Failed to init FileInputStream!", e); - } - } else { + if (mInputData == null) { + Log.e(Constants.TAG, "Input data is null!"); return data; } - if (inputData != null) - generateListOfKeyrings(inputData); + generateListOfKeyrings(mInputData); return data; }