Java tutorial
/* * Copyright (C) 2011,2012 Charabia authors * * 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.charabia; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAPublicKeySpec; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import javax.crypto.Cipher; import com.google.zxing.integration.android.IntentIntegrator; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Intents; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.app.AlertDialog; import android.app.Dialog; import android.app.AlertDialog.Builder; import android.database.Cursor; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.widget.ImageView; import android.widget.TextView; import android.widget.ListView; import android.widget.Toast; import android.util.Base64; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.support.v4.app.FragmentActivity; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.SimpleCursorAdapter; import android.support.v4.widget.SimpleCursorAdapter.ViewBinder; /** * @author * */ public class SmsViewActivity extends FragmentActivity { private static final int MODE_DIALOG = 0; // Keys share mode private static final int MODE_MAITRE = 0; private static final int MODE_ESCLAVE = MODE_MAITRE + 1; private static final int MODE_SMS = MODE_ESCLAVE + 1; // List of intent private static final int SMS_KEY_CONTACT = 1; private static final int ADD_CONTACT = SMS_KEY_CONTACT + 1; // store the mode of key exchange private int mode = MODE_MAITRE; // RSA keypair use to process exchange of key private KeyPair keypair = null; private String prefPhoneNumber = null; private byte[] key = null; private String phoneNumber = null; // Utilities class instance private Tools tools = new Tools(this); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create the list fragment and add it as our sole content. if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) { CursorLoaderListFragment listFragment = new CursorLoaderListFragment(); getSupportFragmentManager().beginTransaction().add(android.R.id.content, listFragment).commit(); } try { String texte = "bonjour"; byte[] data = tools.encrypt("15555215556", texte.getBytes()); Log.v("CHARABIA", "data=" + Base64.encodeToString(data, Base64.NO_WRAP)); Log.v("CHARABIA", "data=" + Tools.bytesToHex(data)); String result = new String(tools.decrypt("15555215556", data)); Log.v("CHARABIA", "result=" + result); } catch (Exception e) { e.printStackTrace(); } } // Manage state changes @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("mode", mode); outState.putString("prefPhoneNumber", prefPhoneNumber); outState.putSerializable("keypair", keypair); outState.putByteArray("key", key); outState.putString("phoneNumber", phoneNumber); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mode = savedInstanceState.getInt("mode"); prefPhoneNumber = savedInstanceState.getString("prefPhoneNumber"); keypair = (KeyPair) savedInstanceState.getSerializable("keypair"); key = savedInstanceState.getByteArray("key"); phoneNumber = savedInstanceState.getString("phoneNumber"); } @Override public void onResume() { super.onResume(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefPhoneNumber = prefs.getString(PreferencesActivity.PHONE_NUMBER, null); if (prefPhoneNumber == null || prefPhoneNumber.length() <= 0) { Intent intent; intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.setClassName(this, PreferencesActivity.class.getName()); startActivity(intent); intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.setClassName(this, WebViewActivity.class.getName()); intent.setData(Uri.parse(WebViewActivity.getBaseUrl(this, "/help", "enter_phone_number.html"))); startActivity(intent); //Attempt to retrieve old keys android.content.ContentResolver cr = getContentResolver(); android.database.Cursor cursor = cr.query(Data.CONTENT_URI, new String[] { Data._ID, Tools.PHONE, Tools.KEY }, Data.MIMETYPE + "=?", new String[] { Tools.CONTENT_ITEM_TYPE }, null); while (cursor.moveToNext()) { try { tools.updateOrCreateContactKey(cursor.getString(cursor.getColumnIndex(Tools.PHONE)), Base64.decode(cursor.getString(cursor.getColumnIndex(Tools.KEY)), Base64.DEFAULT), false); cr.delete(ContentUris.withAppendedId(Data.CONTENT_URI, cursor.getLong(cursor.getColumnIndex(Data._ID))), null, null); } catch (NoContactException e) { e.printStackTrace(); Toast.makeText(this, "No contact for " + cursor.getColumnIndex(Tools.PHONE), Toast.LENGTH_SHORT) .show(); } } } } @Override public boolean onCreateOptionsMenu(Menu menu) { //return super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return true; } public void buttonShare(View v) { showDialog(MODE_DIALOG); } public void buttonOptions(View view) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.setClassName(this, PreferencesActivity.class.getName()); startActivity(intent); } public void buttonHelp(View view) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.setClassName(this, WebViewActivity.class.getName()); intent.setData(Uri.parse(WebViewActivity.getBaseUrl(this, "/help", "index.html"))); startActivity(intent); } public void buttonAbout(View view) { try { PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.app_name)); builder.setMessage(getString(R.string.info, pi.versionName)); builder.setIcon(R.drawable.ic_launcher); builder.setPositiveButton(R.string.quit, null); builder.show(); } catch (NameNotFoundException e) { e.printStackTrace(); } } public void buttonDirectory(View view) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setClassName(this, PickContactActivity.class.getName()); startActivity(intent); } public void buttonEdit(View view) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setClassName(this, CharabiaActivity.class.getName()); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(intent); } public void buttonQuit(View view) { finish(); } /* Handles item selections */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.main_menu_options: buttonOptions(null); return true; case R.id.main_menu_edit: buttonEdit(null); return true; case R.id.main_menu_share: buttonShare(null); return true; case R.id.main_menu_contacts: buttonDirectory(null); return true; case R.id.main_menu_help: buttonHelp(null); return true; case R.id.main_menu_about: buttonAbout(null); return true; case R.id.main_menu_quit: buttonQuit(null); return true; default: return super.onOptionsItemSelected(item); } } /* Handles dialogs */ @Override protected Dialog onCreateDialog(int id) { Dialog dialog; AlertDialog.Builder builder; switch (id) { case MODE_DIALOG: builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.app_name)); builder.setItems(new String[] { getString(R.string.master), getString(R.string.slave), getString(R.string.by_sms) }, modeListener); dialog = builder.create(); break; default: dialog = null; } return dialog; } private final DialogInterface.OnClickListener modeListener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { mode = i; switch (mode) { case MODE_SMS: //sms Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); startActivityForResult(intent, SMS_KEY_CONTACT); break; case MODE_ESCLAVE: IntentIntegrator.initiateScan(SmsViewActivity.this); break; case MODE_MAITRE: default: //Master KeyPairGenerator gen; try { gen = KeyPairGenerator.getInstance("RSA"); //TODO preference to increase key size and so increase security // but this increase amount of data to show in QRcode and can // be more difficult to read gen.initialize(new RSAKeyGenParameterSpec(256, RSAKeyGenParameterSpec.F4)); keypair = gen.generateKeyPair(); RSAPublicKey pubKey = (RSAPublicKey) keypair.getPublic(); IntentIntegrator.initiateScan(SmsViewActivity.this); IntentIntegrator.shareText(SmsViewActivity.this, prefPhoneNumber + "\n" + pubKey.getModulus() + "\n" + pubKey.getPublicExponent()); return; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } Toast.makeText(getApplicationContext(), R.string.unexpected_error, Toast.LENGTH_LONG).show(); } } }; @Override public void onActivityResult(int reqCode, int resultCode, Intent data) { super.onActivityResult(reqCode, resultCode, data); switch (reqCode) { case SMS_KEY_CONTACT: if (resultCode == RESULT_OK) { Uri uri = data.getData(); ContentResolver cr = getContentResolver(); Cursor cursor = cr.query(uri, new String[] { Contacts.LOOKUP_KEY }, null, null, null); String lookup = null; if (cursor.moveToFirst()) { lookup = cursor.getString(0); } cursor.close(); if (lookup == null) { Toast.makeText(this, R.string.unexpected_error, Toast.LENGTH_LONG).show(); return; } cursor = cr.query(Data.CONTENT_URI, new String[] { Phone.NUMBER }, Data.MIMETYPE + "=? AND " + Data.LOOKUP_KEY + "=?", new String[] { Phone.CONTENT_ITEM_TYPE, lookup }, null); ArrayList<String> options = new ArrayList<String>(); while (cursor.moveToNext()) { options.add(cursor.getString(0)); } cursor.close(); final String[] phoneList = options.toArray(new String[0]); Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.send_invit_on_phone); builder.setItems(phoneList, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { keypair = tools.loadKeyPair(); RSAPublicKey pubKey = (RSAPublicKey) keypair.getPublic(); byte[] encoded = pubKey.getModulus().toByteArray(); byte[] data = new byte[3 + encoded.length]; data[0] = Tools.MAGIC[0]; data[1] = Tools.MAGIC[1]; data[2] = Tools.PUBLIC_KEY_TYPE; System.arraycopy(encoded, 0, data, 3, encoded.length); tools.sendData(phoneList[i], Tools.INVITATION, "", data); } }); builder.create().show(); } else { Toast.makeText(this, R.string.error_create_key, Toast.LENGTH_LONG).show(); } break; case IntentIntegrator.REQUEST_CODE: if (resultCode == RESULT_OK) { try { String contents = data.getStringExtra("SCAN_RESULT"); @SuppressWarnings("unused") String format = data.getStringExtra("SCAN_RESULT_FORMAT"); // Handle successful scan // TODO: add more tests control String[] infos = contents.split("\n"); Cipher rsaCipher = Cipher.getInstance(Tools.RSA_CIPHER_ALGO); if (mode == MODE_ESCLAVE) { // Save key and show crypted key on QRCode key = tools.generateKeyAES().getEncoded(); KeyFactory keyFact = KeyFactory.getInstance("RSA"); PublicKey pubkey = keyFact.generatePublic( new RSAPublicKeySpec(new BigInteger(infos[1]), new BigInteger(infos[2]))); rsaCipher.init(Cipher.ENCRYPT_MODE, pubkey); int blockSize = rsaCipher.getBlockSize(); int nbBlock = key.length / blockSize; int reste = key.length % blockSize; byte[] cryptedKey = new byte[(nbBlock + 1) * rsaCipher.getOutputSize(blockSize)]; int offset = 0; for (int i = 0; i < nbBlock; i++) { offset += rsaCipher.doFinal(key, i * blockSize, blockSize, cryptedKey, offset); } rsaCipher.doFinal(key, nbBlock * blockSize, reste, cryptedKey, offset); IntentIntegrator.shareText(SmsViewActivity.this, prefPhoneNumber + "\n" + Base64.encodeToString(cryptedKey, Base64.NO_WRAP)); } else { // We have read crypted key, so decode it rsaCipher.init(Cipher.DECRYPT_MODE, keypair.getPrivate()); byte[] cryptedData = Base64.decode(infos[1], Base64.NO_WRAP); int blockSize = rsaCipher.getBlockSize(); int nbBlock = cryptedData.length / blockSize; int offset = 0; byte[] tempKey = new byte[(nbBlock + 1) * blockSize]; for (int i = 0; i < nbBlock; i++) { offset += rsaCipher.doFinal(cryptedData, i * blockSize, blockSize, tempKey, offset); } key = new byte[offset]; System.arraycopy(tempKey, 0, key, 0, offset); } phoneNumber = infos[0]; // store the key // TODO dialog to confirm add contact in mode SLAVE try { new Tools(this).updateOrCreateContactKey(phoneNumber, key); } catch (NoContactException e) { e.printStackTrace(); // propose to add contact Intent newIntent = new Intent(Intents.SHOW_OR_CREATE_CONTACT); newIntent.setData(Uri.fromParts("tel", phoneNumber, null)); startActivityForResult(newIntent, ADD_CONTACT); return; } Toast.makeText(this, getString(R.string.contact_added) + "\n" + phoneNumber, Toast.LENGTH_LONG) .show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, R.string.error_create_key, Toast.LENGTH_LONG).show(); } } else { // TODO: string Toast.makeText(this, R.string.fail_reading_tag, Toast.LENGTH_LONG).show(); } break; case ADD_CONTACT: try { tools.updateOrCreateContactKey(phoneNumber, key); Toast.makeText(this, getString(R.string.contact_added) + "\n" + phoneNumber, Toast.LENGTH_LONG) .show(); } catch (NoContactException e) { e.printStackTrace(); Toast.makeText(this, R.string.error_create_key, Toast.LENGTH_LONG).show(); } break; } } public static class viewBinder implements ViewBinder { private Context context; public viewBinder(Context context) { this.context = context; } @Override public boolean setViewValue(View v, Cursor cursor, int columnIndex) { if (cursor.getColumnIndex(OpenHelper.ID) == columnIndex) { ImageView iv = (ImageView) v.findViewById(R.id.photo); TextView tv = (TextView) v.findViewById(R.id.line1); String phoneNumber = cursor.getString(cursor.getColumnIndex(OpenHelper.PHONE)); try { StringBuffer displayText = new StringBuffer(); //String lookupKey = tools.getLookupFromPhoneNumber(phoneNumber); //Uri contactUri = Contacts.lookupContact(context.getContentResolver(), // Contacts.getLookupUri(0, lookupKey)); Uri contactUri = Uri.parse(cursor.getString(cursor.getColumnIndex(OpenHelper.CONTACT_URI))); Cursor cname = context.getContentResolver().query(contactUri, new String[] { Contacts.DISPLAY_NAME }, null, null, null); if (cname.moveToFirst()) { displayText.append(cname.getString(0)); } else { //displayName.append(context.getString(R.string.unknow)); displayText.append(phoneNumber); } cname.close(); //displayName.append("\n"); //displayName.append(phoneNumber); DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); long date = cursor.getLong(cursor.getColumnIndex(OpenHelper.MSG_DATE)); String stringDateTime = df.format(new Date(date)); int type = cursor.getInt(cursor.getColumnIndex(OpenHelper.MSG_TYPE)); if (type == Tools.MESSAGE) { displayText.append("\n"); displayText.append(context.getString(R.string.message)); displayText.append("\n"); displayText.append(context.getString(R.string.sending)); tv.setTextColor(Color.WHITE); } else if (type == Tools.MESSAGE_SEND) { displayText.append("\n"); displayText.append(context.getString(R.string.message)); displayText.append("\n"); displayText.append(stringDateTime); tv.setTextColor(Color.WHITE); } else if (type == Tools.MESSAGE_RECEIVED) { tv.setTextColor(Color.BLUE); displayText.append("\n"); displayText.append(context.getString(R.string.message_received)); displayText.append("\n"); displayText.append(stringDateTime); } else if (type == Tools.INVITATION) { tv.setTextColor(Color.GREEN); displayText.append("\n"); displayText.append(context.getString(R.string.invitation)); displayText.append("\n"); displayText.append(context.getString(R.string.sending)); } else if (type == Tools.INVITATION_SEND) { tv.setTextColor(Color.GREEN); displayText.append("\n"); displayText.append(context.getString(R.string.invitation)); displayText.append("\n"); displayText.append(stringDateTime); } else if (type == Tools.INVITATION_RECEIVED) { tv.setTextColor(Color.YELLOW); displayText.append("\n"); displayText.append(context.getString(R.string.invitation_received)); displayText.append("\n"); displayText.append(stringDateTime); } else if (type == Tools.INVITATION_ANSWER) { tv.setTextColor(Color.MAGENTA); displayText.append("\n"); displayText.append(context.getString(R.string.invitation_answer)); displayText.append("\n"); displayText.append(context.getString(R.string.sending)); } else if (type == Tools.INVITATION_ANSWER_SEND) { tv.setTextColor(Color.MAGENTA); displayText.append("\n"); displayText.append(context.getString(R.string.invitation_answer)); displayText.append("\n"); displayText.append(stringDateTime); } tv.setText(displayText); java.io.InputStream input = Contacts.openContactPhotoInputStream(context.getContentResolver(), contactUri); if (input != null) { iv.setImageBitmap(BitmapFactory.decodeStream(input)); try { input.close(); } catch (IOException e) { e.printStackTrace(); } } else { iv.setImageResource(R.drawable.ic_launcher); } return true; } catch (Exception e) { e.printStackTrace(); iv.setImageResource(android.R.drawable.ic_secure); tv.setTextColor(Color.RED); tv.setText("erreur" + "\n" + phoneNumber); return true; } } return false; } } public static class CursorLoaderListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> { private static final String TAG = "CHARABIA"; // Loader private static final int CONTACTS_LOADER = 1; private SimpleCursorAdapter mAdapter = null; private long id = -1; @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setEmptyText(getActivity().getString(R.string.no_action)); mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.list_item, null, new String[] { OpenHelper.ID, }, new int[] { R.id.item }, 0); mAdapter.setViewBinder(new viewBinder(getActivity())); setListAdapter(mAdapter); setListShown(false); getLoaderManager().initLoader(CONTACTS_LOADER, null, this); if (savedInstanceState != null) { } /* getListView().setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setClassName(getActivity(), CharabiaActivity.class.getName()); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(intent); return true; } }); */ } private void deleteId(long id) { ContentResolver cr = getActivity().getContentResolver(); cr.delete(ContentUris.withAppendedId(DataProvider.MSG_CONTENT_URI, id), null, null); } private void dialogMessageSend(final long id, String displayName, Drawable photo, String message) { Builder builder = new AlertDialog.Builder(getActivity()); if (photo == null) { builder.setIcon(R.drawable.ic_launcher); } else { builder.setIcon(photo); } builder.setNegativeButton(R.string.clear, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { deleteId(id); } }); builder.setPositiveButton(R.string.ok, null); builder.setTitle(displayName); builder.setMessage(message); builder.create().show(); } private void dialogMessageReceived(final long id, String displayName, Drawable photo, String message) { Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(displayName); if (photo != null) { builder.setIcon(photo); } else { builder.setIcon(R.drawable.ic_launcher); } builder.setMessage(message); builder.setNegativeButton(R.string.clear, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { deleteId(id); } }); builder.setPositiveButton(R.string.save, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }); builder.create().show(); } private void dialogInvitationReceived(final long id, String displayName, Drawable photo, String message) { Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(displayName); if (photo == null) { builder.setIcon(R.drawable.ic_launcher); } else { builder.setIcon(photo); } builder.setMessage(message); builder.setNegativeButton(R.string.refuse, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }); builder.setPositiveButton(R.string.accept, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { //TODO: } }); builder.create().show(); } private void dialogInvitationAnswer(final long id, String displayName, Drawable photo, String message) { Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(displayName); if (photo == null) { builder.setIcon(R.drawable.ic_launcher); } else { builder.setIcon(photo); } builder.setMessage(message); builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }); builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }); builder.create().show(); } @Override public void onListItemClick(ListView lv, View v, int position, long id) { this.id = id; try { Cursor cursor = mAdapter.getCursor(); int type = 0; String message = null; Uri contactUri = null; String phoneNumber = null; if (cursor.moveToPosition(position)) { phoneNumber = cursor.getString(cursor.getColumnIndex(OpenHelper.PHONE)); type = cursor.getInt(cursor.getColumnIndex(OpenHelper.MSG_TYPE)); int count = cursor.getInt(cursor.getColumnIndex(OpenHelper.COUNTER)); message = "attempt " + count + "," + cursor.getString(cursor.getColumnIndex(OpenHelper.MSG_ERROR)); if (message == null || message.equals("")) { message = cursor.getString(cursor.getColumnIndex(OpenHelper.MSG_TEXT)); } contactUri = Uri.parse(cursor.getString(cursor.getColumnIndex(OpenHelper.CONTACT_URI))); } ContentResolver cr = getActivity().getContentResolver(); Cursor cname = cr.query(contactUri, new String[] { Contacts.DISPLAY_NAME }, null, null, null); String displayName = null; if (cname.moveToFirst()) { displayName = cname.getString(0); } else { displayName = getActivity().getString(R.string.unknow); } cname.close(); java.io.InputStream input = Contacts.openContactPhotoInputStream(cr, contactUri); Drawable photo = null; if (input != null) { photo = Drawable.createFromStream(input, null); } if (type == Tools.MESSAGE || type == Tools.MESSAGE_SEND) { dialogMessageSend(id, displayName, photo, message); } else if (type == Tools.MESSAGE_RECEIVED) { dialogMessageReceived(id, displayName, photo, message); } else if (type == Tools.INVITATION || type == Tools.INVITATION_SEND) { dialogMessageSend(id, displayName, photo, message); } else if (type == Tools.INVITATION_RECEIVED) { dialogInvitationReceived(id, displayName, photo, message); } else if (type == Tools.INVITATION_ANSWER || type == Tools.INVITATION_ANSWER_SEND) { dialogInvitationAnswer(id, displayName, photo, message); } else { throw new Exception("Unexpected error"); } } catch (Exception e) { e.printStackTrace(); final long _id = id; Builder builder = new AlertDialog.Builder(getActivity()); builder.setIcon(R.drawable.ic_launcher); builder.setNegativeButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { ContentResolver cr = getActivity().getContentResolver(); cr.delete(ContentUris.withAppendedId(DataProvider.MSG_CONTENT_URI, _id), null, null); } }); builder.setPositiveButton(R.string.no, null); builder.setTitle(R.string.delete); builder.setMessage(R.string.unexpected_error); builder.create().show(); } } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader(getActivity(), DataProvider.MSG_CONTENT_URI, new String[] { OpenHelper.ID, OpenHelper.PHONE, OpenHelper.CONTACT_URI, OpenHelper.MSG_TYPE, OpenHelper.MSG_DATE, OpenHelper.MSG_TEXT, OpenHelper.MSG_STATUS, OpenHelper.COUNTER, OpenHelper.MSG_ERROR }, null, null, null); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { mAdapter.swapCursor(data); // The list should now be shown. if (isResumed()) { setListShown(true); } else { setListShownNoAnimation(true); } } @Override public void onLoaderReset(Loader<Cursor> loader) { mAdapter.swapCursor(null); } } }