aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2015-02-23 21:52:04 +0100
committerDominik Schürmann <dominik@dominikschuermann.de>2015-02-23 21:52:04 +0100
commit2064d81aef27492e5f9f13a14375fc505bf105ad (patch)
treef3727fb723f81619182e0af643f33a683522fbe7
parentdd3af50956ec80502f9f14e91cffbd271cc232fd (diff)
downloadopen-keychain-2064d81aef27492e5f9f13a14375fc505bf105ad.tar.gz
open-keychain-2064d81aef27492e5f9f13a14375fc505bf105ad.tar.bz2
open-keychain-2064d81aef27492e5f9f13a14375fc505bf105ad.zip
Refactor AppsListFragment
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java278
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml1
2 files changed, 142 insertions, 137 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java
index 976ce20d6..506b2da7f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2013-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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
@@ -50,8 +50,7 @@ import org.sufficientlysecure.keychain.util.Log;
public class AppsListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
- // This is the Adapter being used to display the list's data.
- RegisteredAppsAdapter mAdapter;
+ AppsAdapter mAdapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
@@ -66,7 +65,7 @@ public class AppsListFragment extends ListFragment implements
if (installed) {
if (registered) {
- // edit app settings
+ // Edit app settings
Intent intent = new Intent(getActivity(), AppSettingsActivity.class);
intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(selectedPackageName));
startActivity(intent);
@@ -75,9 +74,10 @@ public class AppsListFragment extends ListFragment implements
PackageManager manager = getActivity().getPackageManager();
try {
i = manager.getLaunchIntentForPackage(selectedPackageName);
- if (i == null)
+ if (i == null) {
throw new PackageManager.NameNotFoundException();
- // start like the Android launcher would do
+ }
+ // Start like the Android launcher would do
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
@@ -91,30 +91,32 @@ public class AppsListFragment extends ListFragment implements
Uri.parse("market://details?id=" + selectedPackageName)));
} catch (ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW,
- Uri.parse("http://play.google.com/store/apps/details?id=" + selectedPackageName)));
+ Uri.parse("https://play.google.com/store/apps/details?id=" + selectedPackageName)));
}
}
}
});
- // Give some text to display if there is no data. In a real
- // application this would come from a resource.
- setEmptyText(getString(R.string.api_no_apps));
+ // NOTE: No setEmptyText(), we always have the default entries
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
// Create an empty adapter we will use to display the loaded data.
- mAdapter = new RegisteredAppsAdapter(getActivity(), null, 0);
+ mAdapter = new AppsAdapter(getActivity(), null, 0);
setListAdapter(mAdapter);
- // Loader is started in onResume!
+ // NOTE: Loader is started in onResume!
}
@Override
public void onResume() {
super.onResume();
- // after coming back from Google Play -> reload
+
+ // Start out with a progress indicator.
+ setListShown(false);
+
+ // After coming back from Google Play -> reload
getLoaderManager().restartLoader(0, null, this);
}
@@ -123,7 +125,6 @@ public class AppsListFragment extends ListFragment implements
private static final String TEMP_COLUMN_REGISTERED = "REGISTERED";
private static final String TEMP_COLUMN_ICON_RES_ID = "ICON_RES_ID";
- // These are the Contacts rows that we will retrieve.
static final String[] PROJECTION = new String[]{
ApiApps._ID, // 0
ApiApps.PACKAGE_NAME, // 1
@@ -149,106 +150,17 @@ public class AppsListFragment extends ListFragment implements
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
- return new CursorLoader(getActivity(), baseUri, PROJECTION, null, null,
+ return new AppsLoader(getActivity(), baseUri, PROJECTION, null, null,
ApiApps.PACKAGE_NAME + " COLLATE LOCALIZED ASC");
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- MatrixCursor availableAppsCursor = new MatrixCursor(new String[]{
- ApiApps._ID,
- ApiApps.PACKAGE_NAME,
- TEMP_COLUMN_NAME,
- TEMP_COLUMN_INSTALLED,
- TEMP_COLUMN_REGISTERED,
- TEMP_COLUMN_ICON_RES_ID
- });
- // NOTE: SORT ascending by package name, this is REQUIRED for CursorJoiner!
- // Drawables taken from projects res/drawables-xxhdpi/ic_launcher.png
- availableAppsCursor.addRow(new Object[]{1, "com.fsck.k9", "K-9 Mail", 0, 0, R.drawable.apps_k9});
- availableAppsCursor.addRow(new Object[]{1, "com.zeapo.pwdstore", "Password Store", 0, 0, R.drawable.apps_password_store});
- availableAppsCursor.addRow(new Object[]{1, "eu.siacs.conversations", "Conversations (Instant Messaging)", 0, 0, R.drawable.apps_conversations});
-
- MatrixCursor mergedCursor = new MatrixCursor(new String[]{
- ApiApps._ID,
- ApiApps.PACKAGE_NAME,
- TEMP_COLUMN_NAME,
- TEMP_COLUMN_INSTALLED,
- TEMP_COLUMN_REGISTERED,
- TEMP_COLUMN_ICON_RES_ID
- });
-
- CursorJoiner joiner = new CursorJoiner(
- availableAppsCursor,
- new String[]{ApiApps.PACKAGE_NAME},
- data,
- new String[]{ApiApps.PACKAGE_NAME});
- for (CursorJoiner.Result joinerResult : joiner) {
- switch (joinerResult) {
- case LEFT: {
- // handle case where a row in availableAppsCursor is unique
- String packageName = availableAppsCursor.getString(INDEX_PACKAGE_NAME);
-
- mergedCursor.addRow(new Object[]{
- 1, // no need for unique _ID
- packageName,
- availableAppsCursor.getString(INDEX_NAME),
- isInstalled(packageName),
- 0,
- availableAppsCursor.getInt(INDEX_ICON_RES_ID)
- });
- break;
- }
- case RIGHT: {
- // handle case where a row in data is unique
- String packageName = data.getString(INDEX_PACKAGE_NAME);
-
- mergedCursor.addRow(new Object[]{
- 1, // no need for unique _ID
- packageName,
- null,
- isInstalled(packageName),
- 1, // registered!
- R.drawable.ic_launcher // icon is retrieved later
- });
- break;
- }
- case BOTH: {
- // handle case where a row with the same key is in both cursors
- String packageName = data.getString(INDEX_PACKAGE_NAME);
-
- String name;
- if (isInstalled(packageName) == 1) {
- name = data.getString(INDEX_NAME);
- } else {
- // if not installed take name from available apps list
- name = availableAppsCursor.getString(INDEX_NAME);
- }
-
- mergedCursor.addRow(new Object[]{
- 1, // no need for unique _ID
- packageName,
- name,
- isInstalled(packageName),
- 1, // registered!
- R.drawable.ic_launcher // icon is retrieved later
- });
- break;
- }
- }
- }
-
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
- mAdapter.swapCursor(mergedCursor);
- }
+ mAdapter.swapCursor(data);
- private int isInstalled(String packageName) {
- try {
- getActivity().getPackageManager().getApplicationInfo(packageName, 0);
- return 1;
- } catch (final PackageManager.NameNotFoundException e) {
- return 0;
- }
+ // The list should now be shown.
+ setListShown(true);
}
public void onLoaderReset(Loader<Cursor> loader) {
@@ -258,12 +170,127 @@ public class AppsListFragment extends ListFragment implements
mAdapter.swapCursor(null);
}
- private class RegisteredAppsAdapter extends CursorAdapter {
+ /**
+ * Besides the queried cursor with all registered apps, this loader also returns non-installed
+ * proposed apps using a MatrixCursor.
+ */
+ private static class AppsLoader extends CursorLoader {
+
+ public AppsLoader(Context context) {
+ super(context);
+ }
+
+ public AppsLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+ super(context, uri, projection, selection, selectionArgs, sortOrder);
+ }
+
+ @Override
+ public Cursor loadInBackground() {
+ // Load registered apps from content provider
+ Cursor data = super.loadInBackground();
+
+ MatrixCursor availableAppsCursor = new MatrixCursor(new String[]{
+ ApiApps._ID,
+ ApiApps.PACKAGE_NAME,
+ TEMP_COLUMN_NAME,
+ TEMP_COLUMN_INSTALLED,
+ TEMP_COLUMN_REGISTERED,
+ TEMP_COLUMN_ICON_RES_ID
+ });
+ // NOTE: SORT ascending by package name, this is REQUIRED for CursorJoiner!
+ // Drawables taken from projects res/drawables-xxhdpi/ic_launcher.png
+ availableAppsCursor.addRow(new Object[]{1, "com.fsck.k9", "K-9 Mail", 0, 0, R.drawable.apps_k9});
+ availableAppsCursor.addRow(new Object[]{1, "com.zeapo.pwdstore", "Password Store", 0, 0, R.drawable.apps_password_store});
+ availableAppsCursor.addRow(new Object[]{1, "eu.siacs.conversations", "Conversations (Instant Messaging)", 0, 0, R.drawable.apps_conversations});
+
+ MatrixCursor mergedCursor = new MatrixCursor(new String[]{
+ ApiApps._ID,
+ ApiApps.PACKAGE_NAME,
+ TEMP_COLUMN_NAME,
+ TEMP_COLUMN_INSTALLED,
+ TEMP_COLUMN_REGISTERED,
+ TEMP_COLUMN_ICON_RES_ID
+ });
+
+ CursorJoiner joiner = new CursorJoiner(
+ availableAppsCursor,
+ new String[]{ApiApps.PACKAGE_NAME},
+ data,
+ new String[]{ApiApps.PACKAGE_NAME});
+ for (CursorJoiner.Result joinerResult : joiner) {
+ switch (joinerResult) {
+ case LEFT: {
+ // handle case where a row in availableAppsCursor is unique
+ String packageName = availableAppsCursor.getString(INDEX_PACKAGE_NAME);
+
+ mergedCursor.addRow(new Object[]{
+ 1, // no need for unique _ID
+ packageName,
+ availableAppsCursor.getString(INDEX_NAME),
+ isInstalled(packageName),
+ 0,
+ availableAppsCursor.getInt(INDEX_ICON_RES_ID)
+ });
+ break;
+ }
+ case RIGHT: {
+ // handle case where a row in data is unique
+ String packageName = data.getString(INDEX_PACKAGE_NAME);
+
+ mergedCursor.addRow(new Object[]{
+ 1, // no need for unique _ID
+ packageName,
+ null,
+ isInstalled(packageName),
+ 1, // registered!
+ R.drawable.ic_launcher // icon is retrieved later
+ });
+ break;
+ }
+ case BOTH: {
+ // handle case where a row with the same key is in both cursors
+ String packageName = data.getString(INDEX_PACKAGE_NAME);
+
+ String name;
+ if (isInstalled(packageName) == 1) {
+ name = data.getString(INDEX_NAME);
+ } else {
+ // if not installed take name from available apps list
+ name = availableAppsCursor.getString(INDEX_NAME);
+ }
+
+ mergedCursor.addRow(new Object[]{
+ 1, // no need for unique _ID
+ packageName,
+ name,
+ isInstalled(packageName),
+ 1, // registered!
+ R.drawable.ic_launcher // icon is retrieved later
+ });
+ break;
+ }
+ }
+ }
+
+ return mergedCursor;
+ }
+
+ private int isInstalled(String packageName) {
+ try {
+ getContext().getPackageManager().getApplicationInfo(packageName, 0);
+ return 1;
+ } catch (final PackageManager.NameNotFoundException e) {
+ return 0;
+ }
+ }
+ }
+
+ private class AppsAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private PackageManager mPM;
- public RegisteredAppsAdapter(Context context, Cursor c, int flags) {
+ public AppsAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
@@ -273,44 +300,23 @@ public class AppsListFragment extends ListFragment implements
/**
* Similar to CursorAdapter.getItemId().
* Required to build Uris for api apps, which are not based on row ids
- *
- * @param position
- * @return
*/
public String getItemPackageName(int position) {
- if (mDataValid && mCursor != null) {
- if (mCursor.moveToPosition(position)) {
- return mCursor.getString(INDEX_PACKAGE_NAME);
- } else {
- return null;
- }
+ if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
+ return mCursor.getString(INDEX_PACKAGE_NAME);
} else {
return null;
}
}
public boolean getItemIsInstalled(int position) {
- if (mDataValid && mCursor != null) {
- if (mCursor.moveToPosition(position)) {
- return (mCursor.getInt(INDEX_INSTALLED) == 1);
- } else {
- return false;
- }
- } else {
- return false;
- }
+ return mDataValid && mCursor != null
+ && mCursor.moveToPosition(position) && (mCursor.getInt(INDEX_INSTALLED) == 1);
}
public boolean getItemIsRegistered(int position) {
- if (mDataValid && mCursor != null) {
- if (mCursor.moveToPosition(position)) {
- return (mCursor.getInt(INDEX_REGISTERED) == 1);
- } else {
- return false;
- }
- } else {
- return false;
- }
+ return mDataValid && mCursor != null
+ && mCursor.moveToPosition(position) && (mCursor.getInt(INDEX_REGISTERED) == 1);
}
@Override
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 97e6a9d71..4a56274d7 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -476,7 +476,6 @@
<string name="intent_send_decrypt">"Decrypt with OpenKeychain"</string>
<!-- Remote API -->
- <string name="api_no_apps">"No registered apps!\n\nA list of supported third-party applications can be found in 'Help'!"</string>
<string name="api_settings_show_info">"Show advanced information"</string>
<string name="api_settings_hide_info">"Hide advanced information"</string>
<string name="api_settings_show_advanced">"Show advanced settings"</string>