Fix file import, commitAllowingStateLoss() was he answer to fragment crashes, PS: I hate fragment lifecycles...

This commit is contained in:
Dominik Schürmann 2013-09-22 21:50:46 +02:00
parent 2e83d92dd0
commit b5c0e4478c
5 changed files with 122 additions and 87 deletions

View File

@ -92,6 +92,65 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
getSupportActionBar().setListNavigationCallbacks(list, this); getSupportActionBar().setListNavigationCallbacks(list, this);
getSupportActionBar().setDisplayShowTitleEnabled(false); 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 // Check that the activity is using the layout version with
// the fragment_container FrameLayout // the fragment_container FrameLayout
if (findViewById(R.id.import_keys_list_container) != null) { 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 // Create an instance of the fragment
mListFragment = ImportKeysListFragment.newInstance(); mListFragment = ImportKeysListFragment.newInstance(bytes, filename);
// Add the fragment to the 'fragment_container' FrameLayout // Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
.replace(R.id.import_keys_list_container, mListFragment).commit(); .replace(R.id.import_keys_list_container, mListFragment)
.commitAllowingStateLoss();
// do it immediately! // do it immediately!
getSupportFragmentManager().executePendingTransactions(); getSupportFragmentManager().executePendingTransactions();
} }
handleActions(getIntent());
} }
@Override @Override
@ -151,7 +209,11 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
} }
public void loadCallback(byte[] importData, String importFilename) { public void loadCallback(byte[] importData, String importFilename) {
mListFragment.load(importData, importFilename); if (mListFragment == null) {
startListFragment(null, importData, importFilename);
} else {
mListFragment.loadNew(importData, importFilename);
}
} }
@Override @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) { // private void importAndSignOld(final long keyId, final String expectedFingerprint) {
// if (expectedFingerprint != null && expectedFingerprint.length() > 0) { // if (expectedFingerprint != null && expectedFingerprint.length() > 0) {
// //

View File

@ -95,18 +95,19 @@ public class ImportKeysFileFragment extends Fragment {
switch (requestCode) { switch (requestCode) {
case Id.request.filename: { case Id.request.filename: {
if (resultCode == Activity.RESULT_OK && data != null) { if (resultCode == Activity.RESULT_OK && data != null) {
String path = null;
try { try {
String path = data.getData().getPath(); path = data.getData().getPath();
Log.d(Constants.TAG, "path=" + path); Log.d(Constants.TAG, "path=" + path);
// set filename to edittext // set filename to edittext
mFilename.setText(path); mFilename.setText(path);
// load data
mImportActivity.loadCallback(null, path);
} catch (NullPointerException e) { } catch (NullPointerException e) {
Log.e(Constants.TAG, "Nullpointer while retrieving path!", e); Log.e(Constants.TAG, "Nullpointer while retrieving path!", e);
} }
// load data
mImportActivity.loadCallback(null, path);
} }
break; break;

View File

@ -17,6 +17,9 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List; import java.util.List;
import org.sufficientlysecure.keychain.Constants; 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.ImportKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import android.app.Activity; import android.app.Activity;
@ -37,6 +41,8 @@ import com.actionbarsherlock.app.SherlockListFragment;
public class ImportKeysListFragment extends SherlockListFragment implements public class ImportKeysListFragment extends SherlockListFragment implements
LoaderManager.LoaderCallbacks<List<ImportKeysListEntry>> { LoaderManager.LoaderCallbacks<List<ImportKeysListEntry>> {
private static final String ARG_FILENAME = "filename";
private static final String ARG_BYTES = "bytes";
private Activity mActivity; private Activity mActivity;
private ImportKeysAdapter mAdapter; private ImportKeysAdapter mAdapter;
@ -59,9 +65,15 @@ public class ImportKeysListFragment extends SherlockListFragment implements
/** /**
* Creates new instance of this fragment * Creates new instance of this fragment
*/ */
public static ImportKeysListFragment newInstance() { public static ImportKeysListFragment newInstance(byte[] bytes, String filename) {
ImportKeysListFragment frag = new ImportKeysListFragment(); ImportKeysListFragment frag = new ImportKeysListFragment();
Bundle args = new Bundle();
args.putByteArray(ARG_BYTES, bytes);
args.putString(ARG_FILENAME, filename);
frag.setArguments(args);
return frag; return frag;
} }
@ -74,15 +86,17 @@ public class ImportKeysListFragment extends SherlockListFragment implements
mActivity = getActivity(); mActivity = getActivity();
// register long press context menu if (getArguments() != null) {
registerForContextMenu(getListView()); mImportFilename = getArguments().getString(ARG_FILENAME);
mKeyBytes = getArguments().getByteArray(ARG_BYTES);
}
// Give some text to display if there is no data. In a real // Give some text to display if there is no data. In a real
// application this would come from a resource. // application this would come from a resource.
setEmptyText(mActivity.getString(R.string.error_nothingImport)); setEmptyText(mActivity.getString(R.string.error_nothingImport));
// Create an empty adapter we will use to display the loaded data. // Create an empty adapter we will use to display the loaded data.
mAdapter = new ImportKeysAdapter(getActivity()); mAdapter = new ImportKeysAdapter(mActivity);
setListAdapter(mAdapter); setListAdapter(mAdapter);
// Start out with a progress indicator. // 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, // Prepare the loader. Either re-connect with an existing one,
// or start a new one. // or start a new one.
// give arguments to onCreateLoader()
getLoaderManager().initLoader(0, null, this); getLoaderManager().initLoader(0, null, this);
} }
@ -105,14 +120,33 @@ public class ImportKeysListFragment extends SherlockListFragment implements
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
} }
public void load(byte[] importData, String importFilename) { public void loadNew(byte[] importData, String importFilename) {
this.mKeyBytes = importData; this.mKeyBytes = importData;
this.mImportFilename = importFilename; this.mImportFilename = importFilename;
getLoaderManager().restartLoader(0, null, this);
} }
@Override @Override
public Loader<List<ImportKeysListEntry>> onCreateLoader(int id, Bundle args) { public Loader<List<ImportKeysListEntry>> 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 @Override

View File

@ -51,6 +51,9 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
public void setData(List<ImportKeysListEntry> data) { public void setData(List<ImportKeysListEntry> data) {
clear(); clear();
if (data != null) { if (data != null) {
this.data = data;
// add data to extended ArrayAdapter
if (Build.VERSION.SDK_INT >= 11) { if (Build.VERSION.SDK_INT >= 11) {
addAll(data); addAll(data);
} else { } else {
@ -58,7 +61,6 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
add(entry); add(entry);
} }
} }
this.data = data;
} }
} }

View File

@ -18,9 +18,6 @@
package org.sufficientlysecure.keychain.ui.adapter; package org.sufficientlysecure.keychain.ui.adapter;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -39,36 +36,24 @@ import android.support.v4.content.AsyncTaskLoader;
public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> { public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> {
Context mContext; Context mContext;
InputData mInputData;
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>(); ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
byte[] mKeyringBytes; public ImportKeysListLoader(Context context, InputData inputData) {
String mImportFilename;
public ImportKeysListLoader(Context context, byte[] keyringBytes, String importFilename) {
super(context); super(context);
this.mContext = context; this.mContext = context;
this.mKeyringBytes = keyringBytes; this.mInputData = inputData;
this.mImportFilename = importFilename;
} }
@Override @Override
public List<ImportKeysListEntry> loadInBackground() { public List<ImportKeysListEntry> loadInBackground() {
InputData inputData = null; if (mInputData == null) {
if (mKeyringBytes != null) { Log.e(Constants.TAG, "Input data is 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 {
return data; return data;
} }
if (inputData != null) generateListOfKeyrings(mInputData);
generateListOfKeyrings(inputData);
return data; return data;
} }