package ca.etsmtl.applets.etsmobile.ui.fragment;
import java.util.ArrayList;
import java.util.Iterator;
import com.octo.android.robospice.persistence.exception.SpiceException;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.accounts.OnAccountsUpdateListener;
import android.app.Activity;
import android.content.ContentProviderOperation;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;
import ca.etsmtl.applets.etsmobile.model.FicheEmploye;
import ca.etsmtl.applets.etsmobile2.R;
public class ContactAdderFragment extends HttpFragment implements
OnAccountsUpdateListener {
public static final String TAG = "ContactsAdder";
public static final String ACCOUNT_NAME = "com.example.android.contactmanager.ContactsAdder.ACCOUNT_NAME";
public static final String ACCOUNT_TYPE = "com.example.android.contactmanager.ContactsAdder.ACCOUNT_TYPE";
private ArrayList<AccountData> mAccounts;
private AccountAdapter mAccountAdapter;
private Spinner mAccountSpinner;
private EditText mContactEmailEditText;
private ArrayList<Integer> mContactEmailTypes;
private Spinner mContactEmailTypeSpinner;
private EditText mContactNameEditText;
private EditText mContactPhoneEditText;
private EditText mContactAddressEditText;
private ArrayList<Integer> mContactPhoneTypes;
private Spinner mContactPhoneTypeSpinner;
private Button mContactSaveButton;
private AccountData mSelectedAccount;
private String prenom;
private String service;
private String empl;
private String titre;
private String courriel;
private String phone;
private String nom;
public static ContactAdderFragment newInstance(Bundle args) {
ContactAdderFragment fragment = new ContactAdderFragment();
if (args != null) {
fragment.setArguments(args);
}
return fragment;
}
/**
* Called when the activity is first created. Responsible for initializing
* the UI.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
Bundle bundle = getArguments();
nom = bundle.getString(BottinDetailsFragment.NOM);
prenom = bundle.getString(BottinDetailsFragment.PRENOM);
titre = bundle.getString(BottinDetailsFragment.TITRE);
service = bundle.getString(BottinDetailsFragment.SERVICE);
empl = bundle.getString(BottinDetailsFragment.EMPLACEMENT);
phone = bundle.getString(BottinDetailsFragment.TELBUREAU);
courriel = bundle.getString(BottinDetailsFragment.COURRIEL);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.contactadder, container, false);
Log.v(TAG, "Activity State: onCreate()");
// final Bundle extras = getArguments();
//
// nom = BottinDetailsFragment.NOM;
// prenom = BottinDetailsFragment.PRENOM;
// service = BottinDetailsFragment.SERVICE;
// // empl = extras.getString("empl");
// titre = BottinDetailsFragment.TITRE;
// courriel = BottinDetailsFragment.COURRIEL;
// phone = BottinDetailsFragment.TELBUREAU;
// Obtain handles to UI objects
mAccountSpinner = (Spinner) v.findViewById(R.id.accountSpinner);
mContactNameEditText = (EditText) v
.findViewById(R.id.contactNameEditText);
System.out.println(prenom);
mContactNameEditText.setText(prenom + " " + nom);
mContactPhoneEditText = (EditText) v
.findViewById(R.id.contactPhoneEditText);
mContactPhoneEditText.setText(phone);
mContactEmailEditText = (EditText) v
.findViewById(R.id.contactEmailEditText);
mContactEmailEditText.setText(courriel);
mContactPhoneTypeSpinner = (Spinner) v
.findViewById(R.id.contactPhoneTypeSpinner);
mContactEmailTypeSpinner = (Spinner) v
.findViewById(R.id.contactEmailTypeSpinner);
mContactAddressEditText = (EditText) v
.findViewById(R.id.addressEditText);
mContactAddressEditText.setText(empl);
mContactSaveButton = (Button) v.findViewById(R.id.contactSaveButton);
// Prepare list of supported account types
// Note: Other types are available in ContactsContract.CommonDataKinds
// Also, be aware that type IDs differ between Phone and Email, and MUST
// be computed
// separately.
mContactPhoneTypes = new ArrayList<Integer>();
mContactPhoneTypes
.add(ContactsContract.CommonDataKinds.Phone.TYPE_HOME);
mContactPhoneTypes
.add(ContactsContract.CommonDataKinds.Phone.TYPE_WORK);
mContactPhoneTypes
.add(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
mContactPhoneTypes
.add(ContactsContract.CommonDataKinds.Phone.TYPE_OTHER);
mContactEmailTypes = new ArrayList<Integer>();
mContactEmailTypes
.add(ContactsContract.CommonDataKinds.Email.TYPE_HOME);
mContactEmailTypes
.add(ContactsContract.CommonDataKinds.Email.TYPE_WORK);
mContactEmailTypes
.add(ContactsContract.CommonDataKinds.Email.TYPE_MOBILE);
mContactEmailTypes
.add(ContactsContract.CommonDataKinds.Email.TYPE_OTHER);
// Prepare model for account spinner
mAccounts = new ArrayList<AccountData>();
mAccountAdapter = new AccountAdapter(getActivity(), mAccounts);
mAccountSpinner.setAdapter(mAccountAdapter);
// Populate list of account types for phone
ArrayAdapter<String> adapter;
adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Iterator<Integer> iter;
iter = mContactPhoneTypes.iterator();
while (iter.hasNext()) {
adapter.add(ContactsContract.CommonDataKinds.Phone.getTypeLabel(
this.getResources(), iter.next(), "undefined").toString());
}
mContactPhoneTypeSpinner.setAdapter(adapter);
mContactPhoneTypeSpinner.setPrompt("select");
// Populate list of account types for email
adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
iter = mContactEmailTypes.iterator();
while (iter.hasNext()) {
adapter.add(ContactsContract.CommonDataKinds.Email.getTypeLabel(
this.getResources(), iter.next(), "undefined").toString());
}
mContactEmailTypeSpinner.setAdapter(adapter);
mContactEmailTypeSpinner.setPrompt("select");
// Prepare the system account manager. On registering the listener
// below, we also ask for
// an initial callback to pre-populate the account list.
AccountManager.get(getActivity()).addOnAccountsUpdatedListener(this,
null, true);
// Register handlers for UI elements
mAccountSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long i) {
updateAccountSelection();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// We don't need to worry about nothing being selected, since
// Spinners don't allow
// this.
}
});
mContactSaveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onSaveButtonClicked();
}
});
return v;
}
/**
* Actions for when the Save button is clicked. Creates a contact entry and
* terminates the activity.
*/
private void onSaveButtonClicked() {
Log.v(TAG, "Save button clicked");
createContactEntry();
getActivity().finish();
}
/**
* Creates a contact entry from the current UI values in the account named
* by mSelectedAccount.
*/
protected void createContactEntry() {
// Get values from UI
final String name = mContactNameEditText.getText().toString();
final String phone = mContactPhoneEditText.getText().toString();
final String email = mContactEmailEditText.getText().toString();
final int phoneType = mContactPhoneTypes.get(mContactPhoneTypeSpinner
.getSelectedItemPosition());
final int emailType = mContactEmailTypes.get(mContactEmailTypeSpinner
.getSelectedItemPosition());
// Prepare contact creation request
//
// Note: We use RawContacts because this data must be associated with a
// particular account.
// The system will aggregate this with any other data for this contact
// and create a
// coresponding entry in the ContactsContract.Contacts provider for us.
final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation
.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE,
mSelectedAccount.getType())
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME,
mSelectedAccount.getName()).build());
ops.add(ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
name)
// .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,name)
// .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,prenom)
.build());
ops.add(ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
phoneType).build());
ops.add(ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
.withValue(ContactsContract.CommonDataKinds.Email.TYPE,
emailType).build());
ops.add(ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
.withValue(
ContactsContract.CommonDataKinds.Organization.COMPANY,
"École de technologie supérieure")
.withValue(
ContactsContract.CommonDataKinds.Organization.DEPARTMENT,
service)
.withValue(ContactsContract.CommonDataKinds.Organization.TITLE,
titre).build());
ops.add(ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
.withValue(
ContactsContract.CommonDataKinds.StructuredPostal.DATA,
empl).build());
// Ask the Contact provider to create a new contact
Log.i(TAG, "Selected account: " + mSelectedAccount.getName() + " ("
+ mSelectedAccount.getType() + ")");
Log.i(TAG, "Creating contact: " + name);
try {
getActivity().getContentResolver().applyBatch(
ContactsContract.AUTHORITY, ops);
} catch (final Exception e) {
// Display warning
final Context ctx = getActivity();
final CharSequence txt = "Echec de la création du contact";
final int duration = Toast.LENGTH_SHORT;
final Toast toast = Toast.makeText(ctx, txt, duration);
toast.show();
// Log exception
Log.e(TAG, "Exceptoin encoutered while inserting contact: " + e);
}
}
/**
* Called when this activity is about to be destroyed by the system.
*/
@Override
public void onDestroy() {
// Remove AccountManager callback
AccountManager.get(getActivity()).removeOnAccountsUpdatedListener(this);
super.onDestroy();
}
/**
* Updates account list spinner when the list of Accounts on the system
* changes. Satisfies OnAccountsUpdateListener implementation.
*/
@Override
public void onAccountsUpdated(Account[] a) {
Log.i(TAG, "Account list update detected");
// Clear out any old data to prevent duplicates
mAccounts.clear();
// Get account data from system
final AuthenticatorDescription[] accountTypes = AccountManager.get(
getActivity()).getAuthenticatorTypes();
// Populate tables
for (final Account element : a) {
// The user may have multiple accounts with the same name, so we
// need to construct a
// meaningful display name for each.
final String systemAccountType = element.type;
final AuthenticatorDescription ad = getAuthenticatorDescription(
systemAccountType, accountTypes);
final AccountData data = new AccountData(element.name, ad);
mAccounts.add(data);
}
// Update the account spinner
mAccountAdapter.notifyDataSetChanged();
}
/**
* Obtain the AuthenticatorDescription for a given account type.
*
* @param type
* The account type to locate.
* @param dictionary
* An array of AuthenticatorDescriptions, as returned by
* AccountManager.
* @return The description for the specified account type.
*/
private static AuthenticatorDescription getAuthenticatorDescription(
String type, AuthenticatorDescription[] dictionary) {
for (final AuthenticatorDescription element : dictionary) {
if (element.type.equals(type)) {
return element;
}
}
// No match found
throw new RuntimeException("Unable to find matching authenticator");
}
/**
* Update account selection. If NO_ACCOUNT is selected, then we prohibit
* inserting new contacts.
*/
private void updateAccountSelection() {
// Read current account selection
mSelectedAccount = (AccountData) mAccountSpinner.getSelectedItem();
}
/**
* A container class used to repreresent all known information about an
* account.
*/
private class AccountData {
private final String mName;
private String mType;
private CharSequence mTypeLabel;
private Drawable mIcon;
/**
* @param name
* The name of the account. This is usually the user's email
* address or username.
* @param description
* The description for this account. This will be dictated by
* the type of account returned, and can be obtained from the
* system AccountManager.
*/
public AccountData(String name, AuthenticatorDescription description) {
mName = name;
if (description != null) {
mType = description.type;
// The type string is stored in a resource, so we need to
// convert it into something
// human readable.
final String packageName = description.packageName;
final PackageManager pm = getActivity().getPackageManager();
if (description.labelId != 0) {
mTypeLabel = pm.getText(packageName, description.labelId,
null);
if (mTypeLabel == null) {
throw new IllegalArgumentException(
"LabelID provided, but label not found");
}
} else {
mTypeLabel = "";
}
if (description.iconId != 0) {
mIcon = pm.getDrawable(packageName, description.iconId,
null);
if (mIcon == null) {
throw new IllegalArgumentException(
"IconID provided, but drawable not " + "found");
}
} else {
mIcon = getResources().getDrawable(
android.R.drawable.sym_def_app_icon);
}
}
}
public String getName() {
return mName;
}
public String getType() {
return mType;
}
public CharSequence getTypeLabel() {
return mTypeLabel;
}
public Drawable getIcon() {
return mIcon;
}
@Override
public String toString() {
return mName;
}
}
/**
* Custom adapter used to display account icons and descriptions in the
* account spinner.
*/
private class AccountAdapter extends ArrayAdapter<AccountData> {
public AccountAdapter(Context context,
ArrayList<AccountData> accountData) {
super(context, android.R.layout.simple_spinner_item, accountData);
setDropDownViewResource(R.layout.account_entry);
}
@Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
// Inflate a view template
if (convertView == null) {
final LayoutInflater layoutInflater = getActivity()
.getLayoutInflater();
convertView = layoutInflater.inflate(R.layout.account_entry,
parent, false);
}
final TextView firstAccountLine = (TextView) convertView
.findViewById(R.id.firstAccountLine);
final TextView secondAccountLine = (TextView) convertView
.findViewById(R.id.secondAccountLine);
final ImageView accountIcon = (ImageView) convertView
.findViewById(R.id.accountIcon);
// Populate template
final AccountData data = getItem(position);
firstAccountLine.setText(data.getName());
secondAccountLine.setText(data.getTypeLabel());
Drawable icon = data.getIcon();
if (icon == null) {
icon = getResources().getDrawable(
android.R.drawable.ic_menu_search);
}
accountIcon.setImageDrawable(icon);
return convertView;
}
}
@Override
public void onRequestFailure(SpiceException arg0) {
}
@Override
public void onRequestSuccess(Object arg0) {
}
@Override
void updateUI() {
}
}