added a key server preference, allowing multiple key servers to be added

Update issue 9
Key server preference added.
This commit is contained in:
Thialfihar 2010-08-17 21:49:34 +00:00
parent e4dd80005c
commit 446f4b493d
12 changed files with 479 additions and 0 deletions

View file

@ -187,6 +187,11 @@
android:label="@string/title_preferences"
android:configChanges="keyboardHidden|orientation|keyboard"/>
<activity
android:name=".KeyServerPreferenceActivity"
android:label="@string/title_keyServerPreference"
android:configChanges="keyboardHidden|orientation|keyboard"/>
<service android:name=".Service" />
<provider

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<org.thialfihar.android.apg.ui.widget.KeyServerEditor
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:layout_marginLeft="3dip">
<EditText
android:id="@+id/server"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:inputType="textUri"/>
<ImageButton
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MinusButton"
android:layout_gravity="center_vertical"
android:layout_marginRight="3dip"/>
</LinearLayout>
<View
android:id="@+id/separator"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider"/>
</org.thialfihar.android.apg.ui.widget.KeyServerEditor>

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+android:id/text_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16sp"
android:layout_marginRight="6sp"
android:layout_marginTop="6sp"
android:layout_marginBottom="6sp"
android:layout_weight="1"
android:focusable="true"
android:background="@android:drawable/menuitem_background">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignLeft="@android:id/title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:maxLines="2" />
</RelativeLayout>
<ImageView
android:id="@+id/add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:layout_marginRight="6dip"
android:layout_gravity="center_vertical"
android:clickable="true"
style="@style/PlusButton"/>
</LinearLayout>
<View
android:id="@+id/separator"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider"/>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:orientation="vertical">
<LinearLayout
android:id="@+id/editors"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"/>
</ScrollView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@android:style/ButtonBar">
<Button
android:text="@android:string/ok"
android:id="@+id/btn_ok"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:text="@android:string/cancel"
android:id="@+id/btn_cancel"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>

View file

@ -29,6 +29,7 @@
<string name="title_createKey">Create Key</string>
<string name="title_editKey">Edit Key</string>
<string name="title_preferences">Preferences</string>
<string name="title_keyServerPreference">Key Server Preference</string>
<string name="title_changePassPhrase">Change Pass Phrase</string>
<string name="title_setPassPhrase">Set Pass Phrase</string>
<string name="title_sendEmail">"Send Mail..."</string>
@ -111,6 +112,7 @@
<string name="label_fileCompression">File Compression</string>
<string name="label_language">Language</string>
<string name="label_forceV3Signature">Force V3 Signatures</string>
<string name="label_keyServers">Key Servers</string>
<string name="noKeysSelected">Select</string>
<string name="oneKeySelected">1 Selected</string>
@ -125,6 +127,7 @@
<string name="canSign">can sign</string>
<string name="expired">expired</string>
<string name="notValid">not valid</string>
<string name="nKeyServers">%s key server(s)</string>
<!-- choice_lowerCase: capitalized first word, no punctuation -->
<string name="choice_none">None</string>

View file

@ -34,6 +34,11 @@
android:entryValues="@array/pass_phrase_cache_ttl_values"
android:title="@string/label_passPhraseCacheTtl" />
<PreferenceScreen
android:persistent="false"
android:key="keyServers"
android:title="@string/label_keyServers" />
</PreferenceCategory>
<PreferenceCategory

View file

@ -141,6 +141,7 @@ public class Apg {
public static final String EXTRA_MESSAGE = "message";
public static final String EXTRA_ASCII_ARMOUR = "asciiArmour";
public static final String EXTRA_BINARY = "binary";
public static final String EXTRA_KEY_SERVERS = "keyServers";
public static final String EXTRA_PROGRESS = "progress";
public static final String EXTRA_PROGRESS_MAX = "max";

View file

@ -34,5 +34,10 @@ public final class Constants {
public static final String pass_phrase_cache_ttl = "passPhraseCacheTtl";
public static final String language = "language";
public static final String force_v3_signatures = "forceV3Signatures";
public static final String key_servers = "keyServers";
}
public static final class defaults {
public static final String key_servers = "pool.sks-keyservers.net, subkeys.pgp.net, pgp.mit.edu";
}
}

View file

@ -57,6 +57,7 @@ public final class Id {
public static final int secret_keys = 0x21070002;
public static final int filename = 0x21070003;
public static final int output_filename = 0x21070004;
public static final int key_server_preference = 0x21070005;
}
public static final class dialog {

View file

@ -0,0 +1,125 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg;
import java.util.Vector;
import org.thialfihar.android.apg.ui.widget.Editor;
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
import org.thialfihar.android.apg.ui.widget.KeyServerEditor;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
public class KeyServerPreferenceActivity extends BaseActivity
implements OnClickListener, EditorListener {
private LayoutInflater mInflater;
private ViewGroup mEditors;
private View mAdd;
private TextView mTitle;
private TextView mSummary;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.key_server_preference);
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mTitle = (TextView) findViewById(R.id.title);
mSummary = (TextView) findViewById(R.id.summary);
mTitle.setText(R.string.label_keyServers);
mEditors = (ViewGroup) findViewById(R.id.editors);
mAdd = findViewById(R.id.add);
mAdd.setOnClickListener(this);
Intent intent = getIntent();
String servers[] = intent.getStringArrayExtra(Apg.EXTRA_KEY_SERVERS);
if (servers != null) {
for (int i = 0; i < servers.length; ++i) {
KeyServerEditor view = (KeyServerEditor) mInflater.inflate(R.layout.key_server_editor, mEditors, false);
view.setEditorListener(this);
view.setValue(servers[i]);
mEditors.addView(view);
}
}
Button okButton = (Button) findViewById(R.id.btn_ok);
okButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
okClicked();
}
});
Button cancelButton = (Button) findViewById(R.id.btn_cancel);
cancelButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
cancelClicked();
}
});
}
public void onDeleted(Editor editor) {
// nothing to do
}
public void onClick(View v) {
KeyServerEditor view = (KeyServerEditor) mInflater.inflate(R.layout.key_server_editor, mEditors, false);
view.setEditorListener(this);
mEditors.addView(view);
}
private void cancelClicked() {
setResult(RESULT_CANCELED, null);
finish();
}
private void okClicked() {
Intent data = new Intent();
Vector<String> servers = new Vector<String>();
for (int i = 0; i < mEditors.getChildCount(); ++i) {
KeyServerEditor editor = (KeyServerEditor) mEditors.getChildAt(i);
String tmp = editor.getValue();
if (tmp.length() > 0) {
servers.add(tmp);
}
}
String[] dummy = new String[0];
data.putExtra(Apg.EXTRA_KEY_SERVERS, servers.toArray(dummy));
setResult(RESULT_OK, data);
finish();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// override this, so no option menu is added (as would be in BaseActivity), since
// we're still in preferences
return true;
}
}

View file

@ -1,5 +1,7 @@
package org.thialfihar.android.apg;
import java.util.Vector;
import org.bouncycastle2.bcpg.HashAlgorithmTags;
import org.bouncycastle2.openpgp.PGPEncryptedData;
@ -133,4 +135,35 @@ public class Preferences {
editor.putBoolean(Constants.pref.has_seen_help, value);
editor.commit();
}
public String[] getKeyServers() {
String rawData = mSharedPreferences.getString(Constants.pref.key_servers,
Constants.defaults.key_servers);
Vector<String> servers = new Vector<String>();
String chunks[] = rawData.split(",");
for (int i = 0; i < chunks.length; ++i) {
String tmp = chunks[i].trim();
if (tmp.length() > 0) {
servers.add(tmp);
}
}
return servers.toArray(chunks);
}
public void setKeyServers(String[] value) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
String rawData = "";
for (int i = 0; i < value.length; ++i) {
String tmp = value[i].trim();
if (tmp.length() == 0) {
continue;
}
if (!"".equals(rawData)) {
rawData += ",";
}
rawData += tmp;
}
editor.putString(Constants.pref.key_servers, rawData);
editor.commit();
}
}

View file

@ -23,11 +23,13 @@ import java.util.Vector;
import org.bouncycastle2.bcpg.HashAlgorithmTags;
import org.bouncycastle2.openpgp.PGPEncryptedData;
import android.content.Intent;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
public class PreferencesActivity extends PreferenceActivity {
private ListPreference mLanguage = null;
@ -38,6 +40,7 @@ public class PreferencesActivity extends PreferenceActivity {
private IntegerListPreference mFileCompression = null;
private CheckBoxPreference mAsciiArmour = null;
private CheckBoxPreference mForceV3Signatures = null;
private PreferenceScreen mKeyServerPreference = null;
private Preferences mPreferences;
@Override
@ -223,6 +226,39 @@ public class PreferencesActivity extends PreferenceActivity {
return false;
}
});
mKeyServerPreference = (PreferenceScreen) findPreference(Constants.pref.key_servers);
String servers[] = mPreferences.getKeyServers();
mKeyServerPreference.setSummary(getResources().getString(R.string.nKeyServers, servers.length));
mKeyServerPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(PreferencesActivity.this,
KeyServerPreferenceActivity.class);
intent.putExtra(Apg.EXTRA_KEY_SERVERS, mPreferences.getKeyServers());
startActivityForResult(intent, Id.request.key_server_preference);
return false;
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Id.request.key_server_preference: {
if (resultCode == RESULT_CANCELED || data == null) {
return;
}
String servers[] = data.getStringArrayExtra(Apg.EXTRA_KEY_SERVERS);
mPreferences.setKeyServers(servers);
mKeyServerPreference.setSummary(getResources().getString(R.string.nKeyServers, servers.length));
break;
}
default: {
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
}
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui.widget;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Vector;
import org.bouncycastle2.openpgp.PGPPublicKey;
import org.bouncycastle2.openpgp.PGPSecretKey;
import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.utils.Choice;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
public class KeyServerEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null;
ImageButton mDeleteButton;
TextView mServer;
public KeyServerEditor(Context context) {
super(context);
}
public KeyServerEditor(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
mServer = (TextView) findViewById(R.id.server);
mDeleteButton = (ImageButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
super.onFinishInflate();
}
public void setValue(String value) {
mServer.setText(value);
}
public String getValue() {
return mServer.getText().toString().trim();
}
@Override
public void onClick(View v) {
final ViewGroup parent = (ViewGroup)getParent();
if (v == mDeleteButton) {
parent.removeView(this);
if (mEditorListener != null) {
mEditorListener.onDeleted(this);
}
}
}
@Override
public void setEditorListener(EditorListener listener) {
mEditorListener = listener;
}
}