diff options
author | Zeapo <mohamed@zenadi.com> | 2014-07-30 02:42:22 +0100 |
---|---|---|
committer | Zeapo <mohamed@zenadi.com> | 2014-07-30 02:42:22 +0100 |
commit | 86ff7a660c194ed908c37344b543368a3f85d7df (patch) | |
tree | 2c6965aa1a7d257a48ecd82f736a548cdffef8a6 /app/src/main/java | |
parent | 8e52356567e897707dbc7879ad46b36c15af67d6 (diff) |
some visual update (fragment list is kept at position) and a preparation for decrypt activity
Diffstat (limited to 'app/src/main/java')
6 files changed, 494 insertions, 39 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/OpenPgpProviderActivity.java b/app/src/main/java/com/zeapo/pwdstore/OpenPgpProviderActivity.java new file mode 100644 index 00000000..3d0e09c3 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/OpenPgpProviderActivity.java @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de> + * + * 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 com.zeapo.pwdstore; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.IntentSender; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import org.openintents.openpgp.OpenPgpError; +import org.openintents.openpgp.OpenPgpSignatureResult; +import org.openintents.openpgp.util.OpenPgpApi; +import org.openintents.openpgp.util.OpenPgpServiceConnection; +import org.openintents.openpgp.util.OpenPgpUtils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; + +public class OpenPgpProviderActivity extends Activity { + private EditText mMessage; + private EditText mCiphertext; + private EditText mEncryptUserIds; + private Button mSign; + private Button mEncrypt; + private Button mSignAndEncrypt; + private Button mDecryptAndVerify; + private EditText mAccount; + private EditText mGetKeyEdit; + private EditText mGetKeyIdsEdit; + private Button mGetKey; + private Button mGetKeyIds; + + private OpenPgpServiceConnection mServiceConnection; + + public static final int REQUEST_CODE_SIGN = 9910; + public static final int REQUEST_CODE_ENCRYPT = 9911; + public static final int REQUEST_CODE_SIGN_AND_ENCRYPT = 9912; + public static final int REQUEST_CODE_DECRYPT_AND_VERIFY = 9913; + public static final int REQUEST_CODE_GET_KEY = 9914; + public static final int REQUEST_CODE_GET_KEY_IDS = 9915; + + public final class Constants { + public static final String TAG = "Keychain"; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.openpgp_provider); + + mMessage = (EditText) findViewById(R.id.crypto_provider_demo_message); + mCiphertext = (EditText) findViewById(R.id.crypto_provider_demo_ciphertext); + mEncryptUserIds = (EditText) findViewById(R.id.crypto_provider_demo_encrypt_user_id); + mSign = (Button) findViewById(R.id.crypto_provider_demo_sign); + mEncrypt = (Button) findViewById(R.id.crypto_provider_demo_encrypt); + mSignAndEncrypt = (Button) findViewById(R.id.crypto_provider_demo_sign_and_encrypt); + mDecryptAndVerify = (Button) findViewById(R.id.crypto_provider_demo_decrypt_and_verify); + mAccount = (EditText) findViewById(R.id.crypto_provider_demo_account); + mGetKeyEdit = (EditText) findViewById(R.id.crypto_provider_demo_get_key_edit); + mGetKeyIdsEdit = (EditText) findViewById(R.id.crypto_provider_demo_get_key_ids_edit); + mGetKey = (Button) findViewById(R.id.crypto_provider_demo_get_key); + mGetKeyIds = (Button) findViewById(R.id.crypto_provider_demo_get_key_ids); + + mSign.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + sign(new Intent()); + } + }); + mEncrypt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + encrypt(new Intent()); + } + }); + mSignAndEncrypt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + signAndEncrypt(new Intent()); + } + }); + mDecryptAndVerify.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + decryptAndVerify(new Intent()); + } + }); + mGetKey.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getKey(new Intent()); + } + }); + mGetKeyIds.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getKeyIds(new Intent()); + } + }); + + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); + String providerPackageName = settings.getString("openpgp_provider_list", ""); + if (TextUtils.isEmpty(providerPackageName)) { + Toast.makeText(this, "No OpenPGP Provider selected!", Toast.LENGTH_LONG).show(); + finish(); + } else { + // bind to service + mServiceConnection = new OpenPgpServiceConnection( + OpenPgpProviderActivity.this, providerPackageName); + mServiceConnection.bindToService(); + } + } + + private void handleError(final OpenPgpError error) { + runOnUiThread(new Runnable() { + + @Override + public void run() { + Toast.makeText(OpenPgpProviderActivity.this, + "onError id:" + error.getErrorId() + "\n\n" + error.getMessage(), + Toast.LENGTH_LONG).show(); + Log.e(Constants.TAG, "onError getErrorId:" + error.getErrorId()); + Log.e(Constants.TAG, "onError getMessage:" + error.getMessage()); + } + }); + } + + private void showToast(final String message) { + runOnUiThread(new Runnable() { + + @Override + public void run() { + Toast.makeText(OpenPgpProviderActivity.this, + message, + Toast.LENGTH_SHORT).show(); + } + }); + } + + /** + * Takes input from message or ciphertext EditText and turns it into a ByteArrayInputStream + * + * @param ciphertext + * @return + */ + private InputStream getInputstream(boolean ciphertext) { + InputStream is = null; + try { + String inputStr; + if (ciphertext) { + inputStr = mCiphertext.getText().toString(); + } else { + inputStr = mMessage.getText().toString(); + } + is = new ByteArrayInputStream(inputStr.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + Log.e(Constants.TAG, "UnsupportedEncodingException", e); + } + + return is; + } + + private class MyCallback implements OpenPgpApi.IOpenPgpCallback { + boolean returnToCiphertextField; + ByteArrayOutputStream os; + int requestCode; + + private MyCallback(boolean returnToCiphertextField, ByteArrayOutputStream os, int requestCode) { + this.returnToCiphertextField = returnToCiphertextField; + this.os = os; + this.requestCode = requestCode; + } + + @Override + public void onReturn(Intent result) { + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: { + showToast("RESULT_CODE_SUCCESS"); + + // encrypt/decrypt/sign/verify + if (os != null) { + try { + Log.d(OpenPgpApi.TAG, "result: " + os.toByteArray().length + + " str=" + os.toString("UTF-8")); + + if (returnToCiphertextField) { + mCiphertext.setText(os.toString("UTF-8")); + } else { + mMessage.setText(os.toString("UTF-8")); + } + } catch (UnsupportedEncodingException e) { + Log.e(Constants.TAG, "UnsupportedEncodingException", e); + } + } + + // verify + if (result.hasExtra(OpenPgpApi.RESULT_SIGNATURE)) { + OpenPgpSignatureResult sigResult + = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); + showToast(sigResult.toString()); + } + + // get key ids + if (result.hasExtra(OpenPgpApi.RESULT_KEY_IDS)) { + long[] keyIds = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS); + String out = "keyIds: "; + for (int i = 0; i < keyIds.length; i++) { + out += OpenPgpUtils.convertKeyIdToHex(keyIds[i]) + ", "; + } + + showToast(out); + } + break; + } + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { + showToast("RESULT_CODE_USER_INTERACTION_REQUIRED"); + + PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); + try { + OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(), + requestCode, null, 0, 0, 0); + } catch (IntentSender.SendIntentException e) { + Log.e(Constants.TAG, "SendIntentException", e); + } + break; + } + case OpenPgpApi.RESULT_CODE_ERROR: { + showToast("RESULT_CODE_ERROR"); + + OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + handleError(error); + break; + } + } + } + } + + public void sign(Intent data) { + data.setAction(OpenPgpApi.ACTION_SIGN); + data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); + data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString()); + + InputStream is = getInputstream(false); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); + api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN)); + } + + public void encrypt(Intent data) { + data.setAction(OpenPgpApi.ACTION_ENCRYPT); + data.putExtra(OpenPgpApi.EXTRA_USER_IDS, mEncryptUserIds.getText().toString().split(",")); + data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); + data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString()); + + InputStream is = getInputstream(false); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); + api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_ENCRYPT)); + } + + public void signAndEncrypt(Intent data) { + data.setAction(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT); + data.putExtra(OpenPgpApi.EXTRA_USER_IDS, mEncryptUserIds.getText().toString().split(",")); + data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); + data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString()); + + InputStream is = getInputstream(false); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); + api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN_AND_ENCRYPT)); + } + + public void decryptAndVerify(Intent data) { + data.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); + data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); + data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString()); + + InputStream is = getInputstream(true); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); + api.executeApiAsync(data, is, os, new MyCallback(false, os, REQUEST_CODE_DECRYPT_AND_VERIFY)); + } + + public void getKey(Intent data) { + data.setAction(OpenPgpApi.ACTION_GET_KEY); + data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString()); + data.putExtra(OpenPgpApi.EXTRA_KEY_ID, Long.decode(mGetKeyEdit.getText().toString())); + + OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); + api.executeApiAsync(data, null, null, new MyCallback(false, null, REQUEST_CODE_GET_KEY)); + } + + public void getKeyIds(Intent data) { + data.setAction(OpenPgpApi.ACTION_GET_KEY_IDS); + data.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, mAccount.getText().toString()); + data.putExtra(OpenPgpApi.EXTRA_USER_IDS, mGetKeyIdsEdit.getText().toString().split(",")); + + OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService()); + api.executeApiAsync(data, null, null, new MyCallback(false, null, REQUEST_CODE_GET_KEY_IDS)); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + Log.d(Constants.TAG, "onActivityResult resultCode: " + resultCode); + + // try again after user interaction + if (resultCode == RESULT_OK) { + /* + * The data originally given to one of the methods above, is again + * returned here to be used when calling the method again after user + * interaction. The Intent now also contains results from the user + * interaction, for example selected key ids. + */ + switch (requestCode) { + case REQUEST_CODE_SIGN: { + sign(data); + break; + } + case REQUEST_CODE_ENCRYPT: { + encrypt(data); + break; + } + case REQUEST_CODE_SIGN_AND_ENCRYPT: { + signAndEncrypt(data); + break; + } + case REQUEST_CODE_DECRYPT_AND_VERIFY: { + decryptAndVerify(data); + break; + } + case REQUEST_CODE_GET_KEY: { + getKey(data); + break; + } + case REQUEST_CODE_GET_KEY_IDS: { + getKeyIds(data); + break; + } + } + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + + if (mServiceConnection != null) { + mServiceConnection.unbindFromService(); + } + } + +}
\ No newline at end of file diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java index de5b0a58..9023320a 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java @@ -47,6 +47,7 @@ public class PasswordFragment extends Fragment implements AbsListView.OnItemClic public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + System.out.println(PasswordRepository.getFilesList().size()); mAdapter = new PasswordAdapter(getActivity(), PasswordRepository.getFilesList()); } @@ -82,7 +83,6 @@ public class PasswordFragment extends Fragment implements AbsListView.OnItemClic mListener = null; } - @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (null != mListener) { diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordRepository.java b/app/src/main/java/com/zeapo/pwdstore/PasswordRepository.java index cdbcb3b0..30181e69 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordRepository.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordRepository.java @@ -45,19 +45,11 @@ public class PasswordRepository { } public static ArrayList<String> getFilesList(){ - // Avoid multiple queries - if (null == mainListOfFiles) { - mainListOfFiles = getFilesList(repository.getWorkTree()); - } - return mainListOfFiles; + return getFilesList(repository.getWorkTree()); } public static LinkedHashMap<String, ArrayList<String>> getPasswords() { - // avoid multiple queries - if (null == mainPasswordMap) { - mainPasswordMap = getPasswords(repository.getWorkTree()); - } - return mainPasswordMap; + return getPasswords(repository.getWorkTree()); } public static File getFile(String name) { @@ -65,6 +57,8 @@ public class PasswordRepository { } public static ArrayList<String> getFilesList(File path){ + if (!path.exists()) return new ArrayList<String>(); + List<File> files = (List<File>) FileUtils.listFiles(path, new String[] {"gpg"}, true); ArrayList<String> filePaths = new ArrayList<String>(); for (File file : files) { @@ -76,6 +70,9 @@ public class PasswordRepository { public static LinkedHashMap<String, ArrayList<String>> getPasswords(File path) { //We need to recover the passwords then parse the files ArrayList<String> passList = getFilesList(path); + + if (passList.size() == 0) return new LinkedHashMap<String, ArrayList<String>>(); + LinkedHashMap<String, ArrayList<String>> passMap = new LinkedHashMap<String, ArrayList<String>>(); passMap.put("Without Category", new ArrayList<String>()); diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java index 8bbdcb4e..6c9eb0b2 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java @@ -1,42 +1,28 @@ package com.zeapo.pwdstore; import android.app.Activity; +import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; -import android.content.Context; import android.content.Intent; -import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import android.widget.TextView; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.filefilter.DirectoryFileFilter; import org.apache.commons.io.filefilter.FileFilterUtils; -import org.apache.commons.io.filefilter.NotFileFilter; -import org.apache.commons.io.filefilter.TrueFileFilter; -import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.ListBranchCommand; -import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.RepositoryBuilder; -import org.eclipse.jgit.storage.file.FileRepositoryBuilder; +import org.openintents.openpgp.util.OpenPgpListPreference; import java.io.File; import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; -import java.util.Collection; -import java.util.List; public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentInteractionListener, PasswordFragment.OnFragmentInteractionListener { + private int listState = 0; @Override protected void onCreate(Bundle savedInstanceState) { @@ -66,11 +52,17 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. -// int id = item.getItemId(); -// if (id == R.id.clone_setting) { -// getClone(); -// return true; -// } + int id = item.getItemId(); + if (id == R.id.user_pref) { + try { + Intent intent = new Intent(this, UserPreference.class); + startActivity(intent); + } catch (Exception e) { + System.out.println("Exception caught :("); + e.printStackTrace(); + } + return true; + } return super.onOptionsItemSelected(item); } @@ -100,7 +92,7 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI switch (status) { case 0: ToCloneOrNot cloneFrag = new ToCloneOrNot(); - fragmentTransaction.replace(R.id.main_layout, cloneFrag); + fragmentTransaction.replace(R.id.main_layout, cloneFrag, "ToCloneOrNot"); fragmentTransaction.commit(); break; case 1: @@ -108,7 +100,12 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI break; default: PasswordFragment passFrag = new PasswordFragment(); - fragmentTransaction.replace(R.id.main_layout, passFrag); + + if (fragmentManager.findFragmentByTag("ToCloneOrNot") == null) { + fragmentTransaction.add(R.id.main_layout, passFrag); + } else { + fragmentTransaction.replace(R.id.main_layout, passFrag); + } fragmentTransaction.commit(); } } @@ -117,12 +114,22 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI @Override public void onFragmentInteraction(String id) { + Intent intent = new Intent(this, PgpHandler.class); + intent.putExtra("FILE_NAME", id); + startActivity(intent); + try { - for (String l : (List<String>) FileUtils.readLines(PasswordRepository.getFile(id), null)) { - System.out.println(l); + byte[] data = new byte[0]; + try { + data = FileUtils.readFileToByteArray(PasswordRepository.getFile(id)); + + } catch (IOException e) { + e.printStackTrace(); } - } catch (IOException e) { - //TODO handle problems + + + } catch (Exception e) { +// TODO handle problems e.printStackTrace(); } } diff --git a/app/src/main/java/com/zeapo/pwdstore/PgpHandler.java b/app/src/main/java/com/zeapo/pwdstore/PgpHandler.java new file mode 100644 index 00000000..22a6f8cc --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/PgpHandler.java @@ -0,0 +1,56 @@ +package com.zeapo.pwdstore; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.TextView; + +import com.zeapo.pwdstore.R; + +import org.openintents.openpgp.util.OpenPgpServiceConnection; + +public class PgpHandler extends Activity { + + + private OpenPgpServiceConnection mServiceConnection; + + public static final int REQUEST_CODE_SIGN = 9910; + public static final int REQUEST_CODE_ENCRYPT = 9911; + public static final int REQUEST_CODE_SIGN_AND_ENCRYPT = 9912; + public static final int REQUEST_CODE_DECRYPT_AND_VERIFY = 9913; + public static final int REQUEST_CODE_GET_KEY = 9914; + public static final int REQUEST_CODE_GET_KEY_IDS = 9915; + + public final class Constants { + public static final String TAG = "Keychain"; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_pgp_handler); + Bundle extra = getIntent().getExtras(); + ((TextView) findViewById(R.id.hhh)).setText(extra.getString("FILE_NAME")); + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.pgp_handler, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + if (id == R.id.action_settings) { + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java new file mode 100644 index 00000000..cc6c1495 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -0,0 +1,13 @@ +package com.zeapo.pwdstore; + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class UserPreference extends PreferenceActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preference); + } +} |