New key view design, using Android flat buttons and Android icons

This commit is contained in:
Dominik Schürmann
2014-05-05 00:58:22 +02:00
parent 4053e1ebd7
commit 6055b0b0da
50 changed files with 1793 additions and 599 deletions

View File

@@ -147,7 +147,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements
}
Log.e(Constants.TAG, "uri: " + mDataUri);
mUserIds = (ListView) findViewById(R.id.user_ids);
mUserIds = (ListView) findViewById(R.id.view_key_user_ids);
mUserIdsAdapter = new ViewKeyUserIdsAdapter(this, null, 0, true);
mUserIds.setAdapter(mUserIdsAdapter);
@@ -203,7 +203,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements
byte[] fingerprintBlob = data.getBlob(INDEX_FINGERPRINT);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
((TextView) findViewById(R.id.fingerprint))
((TextView) findViewById(R.id.view_key_fingerprint))
.setText(PgpKeyHelper.colorizeFingerprint(fingerprint));
}
break;

View File

@@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.ui;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
@@ -31,6 +32,9 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
@@ -42,20 +46,19 @@ import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.helper.ExportHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.TabsAdapter;
import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.SlidingTabLayout;
import java.io.IOException;
import java.util.HashMap;
public class ViewKeyActivity extends ActionBarActivity {
public class ViewKeyActivity extends ActionBarActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
ExportHelper mExportHelper;
ProviderHelper mProviderHelper;
@@ -63,9 +66,15 @@ public class ViewKeyActivity extends ActionBarActivity {
protected Uri mDataUri;
public static final String EXTRA_SELECTED_TAB = "selectedTab";
public static final int TAB_MAIN = 0;
public static final int TAB_SHARE = 1;
public static final int TAB_KEYS = 2;
public static final int TAB_CERTS = 3;
ViewPager mViewPager;
TabsAdapter mTabsAdapter;
// view
private ViewPager mViewPager;
private SlidingTabLayout mSlidingTabLayout;
private PagerTabStripAdapter mTabsAdapter;
public static final int REQUEST_CODE_LOOKUP_KEY = 0x00007006;
@@ -76,6 +85,9 @@ public class ViewKeyActivity extends ActionBarActivity {
private byte[] mNfcKeyringBytes;
private static final int NFC_SENT = 1;
private static final int LOADER_ID_UNIFIED = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
@@ -89,33 +101,67 @@ public class ViewKeyActivity extends ActionBarActivity {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setIcon(android.R.color.transparent);
actionBar.setHomeButtonEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
setContentView(R.layout.view_key_activity);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager = (ViewPager) findViewById(R.id.view_key_pager);
mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.view_key_sliding_tab_layout);
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter = new PagerTabStripAdapter(this);
mViewPager.setAdapter(mTabsAdapter);
int selectedTab = 0;
int switchToTab = TAB_MAIN;
Intent intent = getIntent();
if (intent.getExtras() != null && intent.getExtras().containsKey(EXTRA_SELECTED_TAB)) {
selectedTab = intent.getExtras().getInt(EXTRA_SELECTED_TAB);
switchToTab = intent.getExtras().getInt(EXTRA_SELECTED_TAB);
}
mDataUri = getIntent().getData();
Uri dataUri = getIntent().getData();
if (dataUri == null) {
Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
finish();
return;
}
initNfc(mDataUri);
loadData(dataUri);
initNfc(dataUri);
Bundle mainBundle = new Bundle();
mainBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, mDataUri);
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.key_view_tab_main)),
ViewKeyMainFragment.class, mainBundle, (selectedTab == 0));
mainBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ViewKeyMainFragment.class,
mainBundle, getString(R.string.key_view_tab_main));
Bundle shareBundle = new Bundle();
shareBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ViewKeyShareFragment.class,
mainBundle, getString(R.string.key_view_tab_share));
Bundle keyDetailsBundle = new Bundle();
keyDetailsBundle.putParcelable(ViewKeyKeysFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ViewKeyKeysFragment.class,
keyDetailsBundle, getString(R.string.key_view_tab_keys_details));
Bundle certBundle = new Bundle();
certBundle.putParcelable(ViewKeyCertsFragment.ARG_DATA_URI, mDataUri);
mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.key_view_tab_certs)),
ViewKeyCertsFragment.class, certBundle, (selectedTab == 1));
certBundle.putParcelable(ViewKeyCertsFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ViewKeyCertsFragment.class,
certBundle, getString(R.string.key_view_tab_certs));
// NOTE: must be after adding the tabs!
mSlidingTabLayout.setViewPager(mViewPager);
// switch to tab selected by extra
mViewPager.setCurrentItem(switchToTab);
}
private void loadData(Uri dataUri) {
mDataUri = dataUri;
Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
}
@Override
@@ -143,24 +189,6 @@ public class ViewKeyActivity extends ActionBarActivity {
case R.id.menu_key_view_export_file:
exportToFile(mDataUri, mExportHelper, mProviderHelper);
return true;
case R.id.menu_key_view_share_default_fingerprint:
shareKey(mDataUri, true, mProviderHelper);
return true;
case R.id.menu_key_view_share_default:
shareKey(mDataUri, false, mProviderHelper);
return true;
case R.id.menu_key_view_share_qr_code_fingerprint:
shareKeyQrCode(mDataUri, true);
return true;
case R.id.menu_key_view_share_qr_code:
shareKeyQrCode(mDataUri, false);
return true;
case R.id.menu_key_view_share_nfc:
shareNfc();
return true;
case R.id.menu_key_view_share_clipboard:
copyToClipboard(mDataUri, mProviderHelper);
return true;
case R.id.menu_key_view_delete: {
deleteKey(mDataUri, mExportHelper);
return true;
@@ -209,84 +237,6 @@ public class ViewKeyActivity extends ActionBarActivity {
startActivityForResult(queryIntent, REQUEST_CODE_LOOKUP_KEY);
}
private void shareKey(Uri dataUri, boolean fingerprintOnly, ProviderHelper providerHelper)
throws ProviderHelper.NotFoundException {
String content = null;
if (fingerprintOnly) {
byte[] data = (byte[]) providerHelper.getGenericData(
KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri),
KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
if (data != null) {
String fingerprint = PgpKeyHelper.convertFingerprintToHex(data);
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
} else {
AppMsg.makeText(this, "Bad key selected!",
AppMsg.STYLE_ALERT).show();
return;
}
} else {
// get public keyring as ascii armored string
try {
Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
content = providerHelper.getKeyRingAsArmoredString(uri);
// Android will fail with android.os.TransactionTooLargeException if key is too big
// see http://www.lonestarprod.com/?p=34
if (content.length() >= 86389) {
AppMsg.makeText(this, R.string.key_too_big_for_sharing,
AppMsg.STYLE_ALERT).show();
return;
}
} catch (IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
AppMsg.makeText(this, R.string.error_invalid_data, AppMsg.STYLE_ALERT).show();
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
AppMsg.makeText(this, R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
}
}
if (content != null) {
// let user choose application
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, content);
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent,
getResources().getText(R.string.action_share_key_with)));
} else {
Log.e(Constants.TAG, "content is null!");
}
}
private void shareKeyQrCode(Uri dataUri, boolean fingerprintOnly) {
ShareQrCodeDialogFragment dialog = ShareQrCodeDialogFragment.newInstance(dataUri,
fingerprintOnly);
dialog.show(getSupportFragmentManager(), "shareQrCodeDialog");
}
private void copyToClipboard(Uri dataUri, ProviderHelper providerHelper) {
// get public keyring as ascii armored string
try {
Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
String keyringArmored = providerHelper.getKeyRingAsArmoredString(uri);
ClipboardReflection.copyToClipboard(this, keyringArmored);
AppMsg.makeText(this, R.string.key_copied_to_clipboard, AppMsg.STYLE_INFO)
.show();
} catch (IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
AppMsg.makeText(this, R.string.error_key_processing, AppMsg.STYLE_ALERT).show();
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
AppMsg.makeText(this, R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
}
}
private void shareNfc() {
ShareNfcDialogFragment dialog = ShareNfcDialogFragment.newInstance();
dialog.show(getSupportFragmentManager(), "shareNfcDialog");
}
private void deleteKey(Uri dataUri, ExportHelper exportHelper) {
// Message is received after key is deleted
Handler returnHandler = new Handler() {
@@ -409,4 +359,63 @@ public class ViewKeyActivity extends ActionBarActivity {
}
};
static final String[] UNIFIED_PROJECTION = new String[]{
KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
};
static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
static final int INDEX_UNIFIED_USER_ID = 2;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ID_UNIFIED: {
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
return new CursorLoader(this, baseUri, UNIFIED_PROJECTION, null, null, null);
}
default:
return null;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
/* TODO better error handling? May cause problems when a key is deleted,
* because the notification triggers faster than the activity closes.
*/
// Avoid NullPointerExceptions...
if (data.getCount() == 0) {
return;
}
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
switch (loader.getId()) {
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
// get name, email, and comment from USER_ID
String[] mainUserId = PgpKeyHelper.splitUserId(data.getString(INDEX_UNIFIED_USER_ID));
if (mainUserId[0] != null) {
setTitle(mainUserId[0]);
} else {
setTitle(R.string.user_id_no_name);
}
// get key id from MASTER_KEY_ID
long masterKeyId = data.getLong(INDEX_UNIFIED_MASTER_KEY_ID);
String keyIdStr = PgpKeyHelper.convertKeyIdToHex(masterKeyId);
getSupportActionBar().setSubtitle(keyIdStr);
break;
}
}
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}

View File

@@ -75,6 +75,9 @@ public class ViewKeyCertsFragment extends Fragment
private Uri mDataUri;
// starting with 4 for this fragment
private static final int LOADER_ID = 4;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.view_key_certs_fragment, container, false);
@@ -112,7 +115,7 @@ public class ViewKeyCertsFragment extends Fragment
mAdapter = new CertListAdapter(getActivity(), null);
mStickyList.setAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
getLoaderManager().initLoader(LOADER_ID, null, this);
}
@Override
@@ -208,11 +211,18 @@ public class ViewKeyCertsFragment extends Fragment
// set name and stuff, common to both key types
TextView wSignerKeyId = (TextView) view.findViewById(R.id.signerKeyId);
TextView wSignerUserId = (TextView) view.findViewById(R.id.signerUserId);
TextView wSignerName = (TextView) view.findViewById(R.id.signerName);
TextView wSignStatus = (TextView) view.findViewById(R.id.signStatus);
String signerKeyId = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexSignerKeyId));
String signerUserId = cursor.getString(mIndexSignerUserId);
String[] userId = PgpKeyHelper.splitUserId(cursor.getString(mIndexSignerUserId));
if (userId[0] != null) {
wSignerName.setText(userId[0]);
} else {
wSignerName.setText(R.string.user_id_no_name);
}
wSignerKeyId.setText(signerKeyId);
switch (cursor.getInt(mIndexType)) {
case PGPSignature.DEFAULT_CERTIFICATION: // 0x10
wSignStatus.setText(R.string.cert_default);
@@ -231,8 +241,6 @@ public class ViewKeyCertsFragment extends Fragment
break;
}
wSignerUserId.setText(signerUserId);
wSignerKeyId.setText(signerKeyId);
view.setTag(R.id.tag_mki, cursor.getLong(mIndexMasterKeyId));
view.setTag(R.id.tag_rank, cursor.getLong(mIndexRank));

View File

@@ -0,0 +1,238 @@
/*
* Copyright (C) 2014 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter;
import org.sufficientlysecure.keychain.util.Log;
import java.util.Date;
public class ViewKeyKeysFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final String ARG_DATA_URI = "uri";
private LinearLayout mContainer;
private TextView mAlgorithm;
private TextView mKeyId;
private TextView mExpiry;
private TextView mCreation;
private TextView mFingerprint;
private TextView mSecretKey;
private ListView mKeys;
private static final int LOADER_ID_UNIFIED = 0;
private static final int LOADER_ID_KEYS = 1;
private ViewKeyKeysAdapter mKeysAdapter;
private Uri mDataUri;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.view_key_keys_fragment, container, false);
mContainer = (LinearLayout) view.findViewById(R.id.container);
mKeyId = (TextView) view.findViewById(R.id.key_id);
mAlgorithm = (TextView) view.findViewById(R.id.algorithm);
mCreation = (TextView) view.findViewById(R.id.creation);
mExpiry = (TextView) view.findViewById(R.id.expiry);
mFingerprint = (TextView) view.findViewById(R.id.view_key_fingerprint);
mSecretKey = (TextView) view.findViewById(R.id.secret_key);
mKeys = (ListView) view.findViewById(R.id.keys);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
if (dataUri == null) {
Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
getActivity().finish();
return;
}
loadData(dataUri);
}
private void loadData(Uri dataUri) {
getActivity().setProgressBarIndeterminateVisibility(true);
mContainer.setVisibility(View.GONE);
mDataUri = dataUri;
Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
mKeysAdapter = new ViewKeyKeysAdapter(getActivity(), null, 0);
mKeys.setAdapter(mKeysAdapter);
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
getLoaderManager().initLoader(LOADER_ID_KEYS, null, this);
}
static final String[] UNIFIED_PROJECTION = new String[] {
KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET,
KeyRings.USER_ID, KeyRings.FINGERPRINT,
KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.EXPIRY,
};
static final int INDEX_UNIFIED_MKI = 1;
static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2;
static final int INDEX_UNIFIED_UID = 3;
static final int INDEX_UNIFIED_FINGERPRINT = 4;
static final int INDEX_UNIFIED_ALGORITHM = 5;
static final int INDEX_UNIFIED_KEY_SIZE = 6;
static final int INDEX_UNIFIED_CREATION = 7;
static final int INDEX_UNIFIED_EXPIRY = 8;
static final String[] KEYS_PROJECTION = new String[] {
Keys._ID,
Keys.KEY_ID, Keys.RANK, Keys.ALGORITHM, Keys.KEY_SIZE, Keys.HAS_SECRET,
Keys.CAN_CERTIFY, Keys.CAN_ENCRYPT, Keys.CAN_SIGN, Keys.IS_REVOKED,
Keys.CREATION, Keys.EXPIRY, Keys.FINGERPRINT
};
static final int KEYS_INDEX_CAN_ENCRYPT = 7;
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ID_UNIFIED: {
Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
}
case LOADER_ID_KEYS: {
Uri baseUri = Keys.buildKeysUri(mDataUri);
return new CursorLoader(getActivity(), baseUri, KEYS_PROJECTION, null, null, null);
}
default:
return null;
}
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
/* TODO better error handling? May cause problems when a key is deleted,
* because the notification triggers faster than the activity closes.
*/
// Avoid NullPointerExceptions...
if(data.getCount() == 0) {
return;
}
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
switch (loader.getId()) {
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
if (data.getInt(INDEX_UNIFIED_HAS_ANY_SECRET) != 0) {
mSecretKey.setTextColor(getResources().getColor(R.color.emphasis));
mSecretKey.setText(R.string.secret_key_yes);
} else {
mSecretKey.setTextColor(Color.BLACK);
mSecretKey.setText(getResources().getString(R.string.secret_key_no));
}
// get key id from MASTER_KEY_ID
long masterKeyId = data.getLong(INDEX_UNIFIED_MKI);
String keyIdStr = PgpKeyHelper.convertKeyIdToHex(masterKeyId);
mKeyId.setText(keyIdStr);
// get creation date from CREATION
if (data.isNull(INDEX_UNIFIED_CREATION)) {
mCreation.setText(R.string.none);
} else {
Date creationDate = new Date(data.getLong(INDEX_UNIFIED_CREATION) * 1000);
mCreation.setText(
DateFormat.getDateFormat(getActivity().getApplicationContext()).format(
creationDate));
}
// get expiry date from EXPIRY
if (data.isNull(INDEX_UNIFIED_EXPIRY)) {
mExpiry.setText(R.string.none);
} else {
Date expiryDate = new Date(data.getLong(INDEX_UNIFIED_EXPIRY) * 1000);
mExpiry.setText(
DateFormat.getDateFormat(getActivity().getApplicationContext()).format(
expiryDate));
}
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
getActivity(),
data.getInt(INDEX_UNIFIED_ALGORITHM),
data.getInt(INDEX_UNIFIED_KEY_SIZE)
);
mAlgorithm.setText(algorithmStr);
byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
mFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint));
break;
}
}
case LOADER_ID_KEYS:
mKeysAdapter.swapCursor(data);
break;
}
getActivity().setProgressBarIndeterminateVisibility(false);
mContainer.setVisibility(View.VISIBLE);
}
/**
* This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
* We need to make sure we are no longer using it.
*/
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) {
case LOADER_ID_KEYS:
mKeysAdapter.swapCursor(null);
break;
}
}
}

View File

@@ -19,66 +19,46 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.R;import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter;
import org.sufficientlysecure.keychain.util.Log;
import java.util.Date;
public class ViewKeyMainFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final String ARG_DATA_URI = "uri";
private LinearLayout mContainer;
private TextView mName;
private TextView mEmail;
private TextView mComment;
private TextView mAlgorithm;
private TextView mKeyId;
private TextView mExpiry;
private TextView mCreation;
private TextView mFingerprint;
private TextView mSecretKey;
private BootstrapButton mActionEdit;
private BootstrapButton mActionEncrypt;
private BootstrapButton mActionCertify;
private View mActionEdit;
private View mActionEditDivider;
private View mActionEncrypt;
private View mActionCertify;
private View mActionCertifyDivider;
private ListView mUserIds;
private ListView mKeys;
private static final int LOADER_ID_UNIFIED = 0;
private static final int LOADER_ID_USER_IDS = 1;
private static final int LOADER_ID_KEYS = 2;
private ViewKeyUserIdsAdapter mUserIdsAdapter;
private ViewKeyKeysAdapter mKeysAdapter;
private Uri mDataUri;
@@ -87,20 +67,12 @@ public class ViewKeyMainFragment extends Fragment implements
View view = inflater.inflate(R.layout.view_key_main_fragment, container, false);
mContainer = (LinearLayout) view.findViewById(R.id.container);
mName = (TextView) view.findViewById(R.id.name);
mEmail = (TextView) view.findViewById(R.id.email);
mComment = (TextView) view.findViewById(R.id.comment);
mKeyId = (TextView) view.findViewById(R.id.key_id);
mAlgorithm = (TextView) view.findViewById(R.id.algorithm);
mCreation = (TextView) view.findViewById(R.id.creation);
mExpiry = (TextView) view.findViewById(R.id.expiry);
mFingerprint = (TextView) view.findViewById(R.id.fingerprint);
mSecretKey = (TextView) view.findViewById(R.id.secret_key);
mUserIds = (ListView) view.findViewById(R.id.user_ids);
mKeys = (ListView) view.findViewById(R.id.keys);
mActionEdit = (BootstrapButton) view.findViewById(R.id.action_edit);
mActionEncrypt = (BootstrapButton) view.findViewById(R.id.action_encrypt);
mActionCertify = (BootstrapButton) view.findViewById(R.id.action_certify);
mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids);
mActionEdit = view.findViewById(R.id.view_key_action_edit);
mActionEditDivider = view.findViewById(R.id.view_key_action_edit_divider);
mActionEncrypt = view.findViewById(R.id.view_key_action_encrypt);
mActionCertify = view.findViewById(R.id.view_key_action_certify);
mActionCertifyDivider = view.findViewById(R.id.view_key_action_certify_divider);
return view;
}
@@ -120,11 +92,6 @@ public class ViewKeyMainFragment extends Fragment implements
}
private void loadData(Uri dataUri) {
if (dataUri.equals(mDataUri)) {
Log.d(Constants.TAG, "Same URI, no need to load the data again!");
return;
}
getActivity().setProgressBarIndeterminateVisibility(true);
mContainer.setVisibility(View.GONE);
@@ -135,44 +102,46 @@ public class ViewKeyMainFragment extends Fragment implements
mActionEncrypt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
encryptToContact(mDataUri);
encrypt(mDataUri);
}
});
mActionCertify.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
certifyKey(mDataUri);
certify(mDataUri);
}
});
mActionEdit.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
editKey(mDataUri);
}
});
mUserIdsAdapter = new ViewKeyUserIdsAdapter(getActivity(), null, 0);
mUserIds.setAdapter(mUserIdsAdapter);
mKeysAdapter = new ViewKeyKeysAdapter(getActivity(), null, 0);
mKeys.setAdapter(mKeysAdapter);
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getActivity().getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
getActivity().getSupportLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
getActivity().getSupportLoaderManager().initLoader(LOADER_ID_KEYS, null, this);
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
getLoaderManager().initLoader(LOADER_ID_KEYS, null, this);
}
static final String[] UNIFIED_PROJECTION = new String[] {
KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET,
static final String[] UNIFIED_PROJECTION = new String[]{
KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET,
KeyRings.USER_ID, KeyRings.FINGERPRINT,
KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.EXPIRY,
};
static final int INDEX_UNIFIED_MKI = 1;
static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2;
static final int INDEX_UNIFIED_UID = 3;
static final int INDEX_UNIFIED_USER_ID = 3;
static final int INDEX_UNIFIED_FINGERPRINT = 4;
static final int INDEX_UNIFIED_ALGORITHM = 5;
static final int INDEX_UNIFIED_KEY_SIZE = 6;
static final int INDEX_UNIFIED_CREATION = 7;
static final int INDEX_UNIFIED_EXPIRY = 8;
static final String[] KEYS_PROJECTION = new String[] {
static final String[] KEYS_PROJECTION = new String[]{
Keys._ID,
Keys.KEY_ID, Keys.RANK, Keys.ALGORITHM, Keys.KEY_SIZE, Keys.HAS_SECRET,
Keys.CAN_CERTIFY, Keys.CAN_ENCRYPT, Keys.CAN_SIGN, Keys.IS_REVOKED,
@@ -205,7 +174,7 @@ public class ViewKeyMainFragment extends Fragment implements
* because the notification triggers faster than the activity closes.
*/
// Avoid NullPointerExceptions...
if(data.getCount() == 0) {
if (data.getCount() == 0) {
return;
}
// Swap the new cursor in. (The framework will take care of closing the
@@ -213,81 +182,24 @@ public class ViewKeyMainFragment extends Fragment implements
switch (loader.getId()) {
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
// get name, email, and comment from USER_ID
String[] mainUserId = PgpKeyHelper.splitUserId(data.getString(INDEX_UNIFIED_UID));
if (mainUserId[0] != null) {
getActivity().setTitle(mainUserId[0]);
mName.setText(mainUserId[0]);
} else {
getActivity().setTitle(R.string.user_id_no_name);
mName.setText(R.string.user_id_no_name);
}
mEmail.setText(mainUserId[1]);
mComment.setText(mainUserId[2]);
if (data.getInt(INDEX_UNIFIED_HAS_ANY_SECRET) != 0) {
mSecretKey.setTextColor(getResources().getColor(R.color.emphasis));
mSecretKey.setText(R.string.secret_key_yes);
// certify button
mActionCertify.setVisibility(View.GONE);
mActionCertifyDivider.setVisibility(View.GONE);
// edit button
mActionEdit.setVisibility(View.VISIBLE);
mActionEdit.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
editIntent.setData(
KeyRingData.buildSecretKeyRingUri(mDataUri));
editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
startActivityForResult(editIntent, 0);
}
});
mActionEditDivider.setVisibility(View.VISIBLE);
} else {
mSecretKey.setTextColor(Color.BLACK);
mSecretKey.setText(getResources().getString(R.string.secret_key_no));
// certify button
mActionCertify.setVisibility(View.VISIBLE);
mActionCertifyDivider.setVisibility(View.VISIBLE);
// edit button
mActionEdit.setVisibility(View.GONE);
mActionEditDivider.setVisibility(View.GONE);
}
// get key id from MASTER_KEY_ID
long masterKeyId = data.getLong(INDEX_UNIFIED_MKI);
String keyIdStr = PgpKeyHelper.convertKeyIdToHex(masterKeyId);
mKeyId.setText(keyIdStr);
// get creation date from CREATION
if (data.isNull(INDEX_UNIFIED_CREATION)) {
mCreation.setText(R.string.none);
} else {
Date creationDate = new Date(data.getLong(INDEX_UNIFIED_CREATION) * 1000);
mCreation.setText(
DateFormat.getDateFormat(getActivity().getApplicationContext()).format(
creationDate));
}
// get expiry date from EXPIRY
if (data.isNull(INDEX_UNIFIED_EXPIRY)) {
mExpiry.setText(R.string.none);
} else {
Date expiryDate = new Date(data.getLong(INDEX_UNIFIED_EXPIRY) * 1000);
mExpiry.setText(
DateFormat.getDateFormat(getActivity().getApplicationContext()).format(
expiryDate));
}
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
getActivity(),
data.getInt(INDEX_UNIFIED_ALGORITHM),
data.getInt(INDEX_UNIFIED_KEY_SIZE)
);
mAlgorithm.setText(algorithmStr);
byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
mFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint));
break;
}
}
@@ -307,11 +219,12 @@ public class ViewKeyMainFragment extends Fragment implements
break;
}
} while (data.moveToNext());
if (!canEncrypt) {
if (canEncrypt) {
mActionEncrypt.setVisibility(View.VISIBLE);
} else {
mActionEncrypt.setVisibility(View.GONE);
}
mKeysAdapter.swapCursor(data);
break;
}
getActivity().setProgressBarIndeterminateVisibility(false);
@@ -327,16 +240,13 @@ public class ViewKeyMainFragment extends Fragment implements
case LOADER_ID_USER_IDS:
mUserIdsAdapter.swapCursor(null);
break;
case LOADER_ID_KEYS:
mKeysAdapter.swapCursor(null);
break;
}
}
private void encryptToContact(Uri dataUri) {
private void encrypt(Uri dataUri) {
try {
long keyId = new ProviderHelper(getActivity()).extractOrGetMasterKeyId(dataUri);
long[] encryptionKeyIds = new long[]{ keyId };
long[] encryptionKeyIds = new long[]{keyId};
Intent intent = new Intent(getActivity(), EncryptActivity.class);
intent.setAction(EncryptActivity.ACTION_ENCRYPT);
intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
@@ -347,10 +257,17 @@ public class ViewKeyMainFragment extends Fragment implements
}
}
private void certifyKey(Uri dataUri) {
private void certify(Uri dataUri) {
Intent signIntent = new Intent(getActivity(), CertifyKeyActivity.class);
signIntent.setData(dataUri);
startActivity(signIntent);
}
private void editKey(Uri dataUri) {
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri));
editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
startActivityForResult(editIntent, 0);
}
}

View File

@@ -0,0 +1,313 @@
/*
* Copyright (C) 2014 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
import android.annotation.TargetApi;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.QrCodeUtils;
import java.io.IOException;
public class ViewKeyShareFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final String ARG_DATA_URI = "uri";
private LinearLayout mContainer;
private TextView mFingerprint;
private ImageView mFingerprintQrCode;
private View mFingerprintShareButton;
private View mFingerprintClipboardButton;
private View mKeyShareButton;
private View mKeyClipboardButton;
private View mNfcHelpButton;
private View mNfcPrefsButton;
ProviderHelper mProviderHelper;
private static final int QR_CODE_SIZE = 1000;
private static final int LOADER_ID_UNIFIED = 0;
private Uri mDataUri;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.view_key_share_fragment, container, false);
mProviderHelper = new ProviderHelper(ViewKeyShareFragment.this.getActivity());
mContainer = (LinearLayout) view.findViewById(R.id.container);
mFingerprint = (TextView) view.findViewById(R.id.view_key_fingerprint);
mFingerprintQrCode = (ImageView) view.findViewById(R.id.view_key_fingerprint_qr_code_image);
mFingerprintShareButton = view.findViewById(R.id.view_key_action_fingerprint_share);
mFingerprintClipboardButton = view.findViewById(R.id.view_key_action_fingerprint_clipboard);
mKeyShareButton = view.findViewById(R.id.view_key_action_key_share);
mKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard);
mNfcHelpButton = view.findViewById(R.id.view_key_action_nfc_help);
mNfcPrefsButton = view.findViewById(R.id.view_key_action_nfc_prefs);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mNfcPrefsButton.setVisibility(View.VISIBLE);
} else {
mNfcPrefsButton.setVisibility(View.GONE);
}
mFingerprintQrCode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showQrCodeDialog();
}
});
mFingerprintShareButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
share(mDataUri, mProviderHelper, true, false);
}
});
mFingerprintClipboardButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
share(mDataUri, mProviderHelper, true, true);
}
});
mKeyShareButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
share(mDataUri, mProviderHelper, false, false);
}
});
mKeyClipboardButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
share(mDataUri, mProviderHelper, false, true);
}
});
mNfcHelpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showNfcHelpDialog();
}
});
mNfcPrefsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showNfcPrefs();
}
});
return view;
}
private void share(Uri dataUri, ProviderHelper providerHelper, boolean fingerprintOnly,
boolean toClipboard) {
try {
String content;
if (fingerprintOnly) {
byte[] data = (byte[]) providerHelper.getGenericData(
KeyRings.buildUnifiedKeyRingUri(dataUri),
Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(data);
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
} else {
// get public keyring as ascii armored string
Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
content = providerHelper.getKeyRingAsArmoredString(uri);
}
if (toClipboard) {
ClipboardReflection.copyToClipboard(getActivity(), content);
String message;
if (fingerprintOnly) {
message = getResources().getString(R.string.fingerprint_copied_to_clipboard);
} else {
message = getResources().getString(R.string.key_copied_to_clipboard);
}
AppMsg.makeText(getActivity(), message, AppMsg.STYLE_INFO).show();
} else {
// Android will fail with android.os.TransactionTooLargeException if key is too big
// see http://www.lonestarprod.com/?p=34
if (content.length() >= 86389) {
AppMsg.makeText(getActivity(), R.string.key_too_big_for_sharing,
AppMsg.STYLE_ALERT).show();
return;
}
// let user choose application
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, content);
sendIntent.setType("text/plain");
String title;
if (fingerprintOnly) {
title = getResources().getString(R.string.title_share_fingerprint_with);
} else {
title = getResources().getString(R.string.title_share_key_with);
}
startActivity(Intent.createChooser(sendIntent, title));
}
} catch (IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
AppMsg.makeText(getActivity(), R.string.error_key_processing, AppMsg.STYLE_ALERT).show();
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
}
}
private void showQrCodeDialog() {
ShareQrCodeDialogFragment dialog = ShareQrCodeDialogFragment.newInstance(mDataUri,
true);
dialog.show(ViewKeyShareFragment.this.getActivity().getSupportFragmentManager(), "shareQrCodeDialog");
}
private void showNfcHelpDialog() {
ShareNfcDialogFragment dialog = ShareNfcDialogFragment.newInstance();
dialog.show(getActivity().getSupportFragmentManager(), "shareNfcDialog");
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void showNfcPrefs() {
Intent intentSettings = new Intent(
Settings.ACTION_NFCSHARING_SETTINGS);
startActivity(intentSettings);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
if (dataUri == null) {
Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
getActivity().finish();
return;
}
loadData(dataUri);
}
private void loadData(Uri dataUri) {
getActivity().setProgressBarIndeterminateVisibility(true);
mContainer.setVisibility(View.GONE);
mDataUri = dataUri;
Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
}
static final String[] UNIFIED_PROJECTION = new String[]{
KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET,
KeyRings.USER_ID, KeyRings.FINGERPRINT,
KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.EXPIRY,
};
static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2;
static final int INDEX_UNIFIED_USER_ID = 3;
static final int INDEX_UNIFIED_FINGERPRINT = 4;
static final int INDEX_UNIFIED_ALGORITHM = 5;
static final int INDEX_UNIFIED_KEY_SIZE = 6;
static final int INDEX_UNIFIED_CREATION = 7;
static final int INDEX_UNIFIED_EXPIRY = 8;
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ID_UNIFIED: {
Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
}
default:
return null;
}
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
/* TODO better error handling? May cause problems when a key is deleted,
* because the notification triggers faster than the activity closes.
*/
// Avoid NullPointerExceptions...
if (data.getCount() == 0) {
return;
}
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
switch (loader.getId()) {
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
mFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint));
String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
mFingerprintQrCode.setImageBitmap(
QrCodeUtils.getQRCodeBitmap(qrCodeContent, QR_CODE_SIZE)
);
break;
}
}
}
getActivity().setProgressBarIndeterminateVisibility(false);
mContainer.setVisibility(View.VISIBLE);
}
/**
* This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
* We need to make sure we are no longer using it.
*/
public void onLoaderReset(Loader<Cursor> loader) {
}
}

View File

@@ -28,7 +28,6 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
@@ -106,7 +105,7 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
holder.mainUserId = (TextView) convertView.findViewById(R.id.mainUserId);
holder.mainUserIdRest = (TextView) convertView.findViewById(R.id.mainUserIdRest);
holder.keyId = (TextView) convertView.findViewById(R.id.keyId);
holder.fingerprint = (TextView) convertView.findViewById(R.id.fingerprint);
holder.fingerprint = (TextView) convertView.findViewById(R.id.view_key_fingerprint);
holder.algorithm = (TextView) convertView.findViewById(R.id.algorithm);
holder.status = (TextView) convertView.findViewById(R.id.status);
holder.userIdsList = (LinearLayout) convertView.findViewById(R.id.user_ids_list);

View File

@@ -17,7 +17,7 @@
package org.sufficientlysecure.keychain.ui.adapter;
import android.content.Context;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
@@ -26,8 +26,8 @@ import android.support.v7.app.ActionBarActivity;
import java.util.ArrayList;
public class PagerTabStripAdapter extends FragmentPagerAdapter {
private final Context mContext;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
protected final Activity mActivity;
protected final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
public final Class<?> clss;
@@ -43,7 +43,7 @@ public class PagerTabStripAdapter extends FragmentPagerAdapter {
public PagerTabStripAdapter(ActionBarActivity activity) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActivity = activity;
}
public void addTab(Class<?> clss, Bundle args, String title) {
@@ -60,7 +60,7 @@ public class PagerTabStripAdapter extends FragmentPagerAdapter {
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
return Fragment.instantiate(mActivity, info.clss.getName(), info.args);
}
@Override

View File

@@ -27,6 +27,7 @@ import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
@@ -106,40 +107,55 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView.
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView vRank = (TextView) view.findViewById(R.id.rank);
TextView vUserId = (TextView) view.findViewById(R.id.userId);
TextView vName = (TextView) view.findViewById(R.id.userId);
TextView vAddress = (TextView) view.findViewById(R.id.address);
TextView vComment = (TextView) view.findViewById(R.id.comment);
ImageView vVerified = (ImageView) view.findViewById(R.id.certified);
if (cursor.getInt(mIsPrimary) > 0) {
vRank.setText("+");
} else {
vRank.setText(Integer.toString(cursor.getInt(mIndexRank)));
}
ImageView vPrimaryUserIdIcon = (ImageView) view.findViewById(R.id.primary_user_id_icon);
String[] userId = PgpKeyHelper.splitUserId(cursor.getString(mIndexUserId));
if (userId[0] != null) {
vUserId.setText(userId[0]);
vName.setText(userId[0]);
} else {
vUserId.setText(R.string.user_id_no_name);
vName.setText(R.string.user_id_no_name);
}
if (userId[1] != null) {
vAddress.setText(userId[1]);
vAddress.setVisibility(View.VISIBLE);
} else {
vAddress.setVisibility(View.GONE);
}
if (userId[2] != null) {
vComment.setText(userId[2]);
vComment.setVisibility(View.VISIBLE);
} else {
vComment.setVisibility(View.GONE);
}
// show small star icon for primary user ids
if (cursor.getInt(mIsPrimary) > 0) {
vPrimaryUserIdIcon.setVisibility(View.VISIBLE);
} else {
vPrimaryUserIdIcon.setVisibility(View.GONE);
}
vAddress.setText(userId[1]);
if (cursor.getInt(mIsRevoked) > 0) {
vRank.setText(" ");
// no star icon for revoked user ids!
vPrimaryUserIdIcon.setVisibility(View.GONE);
// set revocation icon
vVerified.setImageResource(R.drawable.key_certify_revoke);
// disable and strike through text for revoked user ids
vUserId.setEnabled(false);
vName.setEnabled(false);
vAddress.setEnabled(false);
vUserId.setText(OtherHelper.strikeOutText(vUserId.getText()));
vName.setText(OtherHelper.strikeOutText(vName.getText()));
vAddress.setText(OtherHelper.strikeOutText(vAddress.getText()));
} else {
vUserId.setEnabled(true);
vName.setEnabled(true);
vAddress.setEnabled(true);
int verified = cursor.getInt(mVerifiedId);
// TODO introduce own resources for this :)
switch (verified) {
case Certs.VERIFIED_SECRET:
vVerified.setImageResource(R.drawable.key_certify_ok_depth0);