Advertisement
Allier

Code sample

Nov 26th, 2014
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 20.02 KB | None | 0 0
  1. /**
  2.  * Class for managing contacts sync related operations
  3.  */
  4. public class ContactsManager {
  5.     /**
  6.      * tag string for LogCat
  7.      */
  8.     private static final String TAG = ContactsManager.class.toString();
  9.  
  10.     ...
  11.  
  12.     /**
  13.      * Retrieve all phone numbers from the android contacts
  14.      * @return ArrayList of strings, where each string is a phone number
  15.      */
  16.     public static synchronized Collection<String> getPhones(Context context) {
  17.         Collection<String> result = new ArrayList<>();
  18.         ContentResolver cr = context.getContentResolver();
  19.  
  20.         Cursor pCur = cr.query(
  21.                 ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
  22.                 null, null, null, null);
  23.         while (pCur.moveToNext()) {
  24.             String phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
  25.             phoneNo = phoneNo.replace(" ", "");
  26.             phoneNo = phoneNo.replace("-", "");
  27.             if (phoneNo.charAt(0) != '+') { // phone number has a country code
  28.                 if (!Character.isDigit(phoneNo.charAt(0)))
  29.                     continue;
  30.  
  31.                 String iso = getUserCountry(context);
  32.  
  33.                 PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
  34.                 try { // adding country code
  35.                     Phonenumber.PhoneNumber localNumber = phoneUtil.parse(phoneNo, iso);
  36.                     if (!phoneUtil.isPossibleNumber(localNumber))
  37.                         continue;
  38.                     phoneNo = phoneUtil.format(localNumber, PhoneNumberUtil.PhoneNumberFormat.E164);
  39.                 } catch (NumberParseException e) {
  40.                     System.err.println("NumberParseException: " + e.toString());
  41.                 }
  42.             }
  43.             if (!result.contains(phoneNo))
  44.                 result.add(phoneNo);
  45.         }
  46.         pCur.close();
  47.  
  48.         return result;
  49.     }
  50.  
  51.     /**
  52.      * Get ISO 3166-1 alpha-2 country code for this device (or null if not available)
  53.      * @param context Context reference to get the TelephonyManager instance from
  54.      * @return country code or null
  55.      */
  56.     private static String getUserCountry(Context context) {
  57.         try {
  58.             final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
  59.             final String simCountry = tm.getSimCountryIso();
  60.             if (simCountry != null && simCountry.length() == 2) { // SIM country code is available
  61.                 return simCountry.toUpperCase();
  62.             }
  63.             else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) { // device is not 3G (would be unreliable)
  64.                 String networkCountry = tm.getNetworkCountryIso();
  65.                 if (networkCountry != null && networkCountry.length() == 2) { // network country code is available
  66.                     return networkCountry.toUpperCase();
  67.                 }
  68.             }
  69.         }
  70.         catch (Exception e) {
  71.             System.err.println("Can't get user country: " + e.toString());
  72.         }
  73.         return null;
  74.     }
  75.  
  76.     /**
  77.      * Synchronize all raw contacts
  78.      *
  79.      * @param context  The context of Authenticator Activity
  80.      * @param account  The username for the account
  81.      * @param contacts The collection of profiles
  82.      */
  83.     public static synchronized void syncContacts(Context context, String account, Collection<Contact> contacts) {
  84.         for (Contact contact : contacts)
  85.             syncContact(context, account, contact);
  86.     }
  87.  
  88.     /**
  89.      * Synchronize raw contact
  90.      *
  91.      * @param context  The context of Authenticator Activity
  92.      * @param account  The username for the account
  93.      * @param contact  The contact to sync
  94.      */
  95.     public static synchronized void syncContact(Context context, String account, Contact contact) {
  96.         if(TextUtils.isEmpty(contact.getPhone()))
  97.             return;
  98.  
  99.         final ContentResolver resolver = context.getContentResolver();
  100.         final BatchOperation batchOperation = new BatchOperation(context, resolver);
  101.  
  102.         Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
  103.                 Uri.encode(contact.getPhone()));
  104.         Cursor contactCursor = resolver.query(
  105.                 lookupUri,
  106.                 new String[]{ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.LOOKUP_KEY},
  107.                 null, null, null);
  108.         if (contactCursor.moveToFirst()) {
  109.             long contactId = contactCursor.getLong(0);
  110.             long rawContactId = lookupRawContact(resolver, contactId);
  111.             if (rawContactId != 0 && !isDeletedRawContact(context, rawContactId)) {
  112.                 backupContact(context, resolver, rawContactId);
  113.                 recreateContact(context, resolver, account, contact, rawContactId, batchOperation);
  114.                 batchOperation.execute();
  115.                 deleteContact(context, rawContactId, batchOperation);
  116.             }
  117.             else
  118.                 addContact(context, account, contact, batchOperation);
  119.         } else
  120.             addContact(context, account, contact, batchOperation);
  121.         contactCursor.close();
  122.  
  123.         batchOperation.execute();
  124.     }
  125.  
  126.     /**
  127.      * Checks if contact marked as deleted
  128.      *
  129.      * @param context       The context of Authenticator Activity
  130.      * @param rowContactId  ID of the verifiable contact      
  131.      */
  132.     private static boolean isDeletedRawContact(Context context, long rawContactId) {
  133.         Cursor c = context.getContentResolver().query(RawContacts.CONTENT_URI,
  134.                 new String[]{RawContacts.DELETED},
  135.                 RawContacts._ID + "=?",
  136.                 new String[]{String.valueOf(rawContactId)}, null);
  137.         c.moveToFirst();
  138.         boolean result = c.getInt(0) > 0;
  139.         c.close();
  140.         return result;
  141.     }
  142.  
  143.     /**
  144.      * Restores previously recreated contacts.
  145.      *
  146.      * @param context  The context of Authenticator Activity
  147.      */
  148.     public static void restoreContact(Context context) {
  149.         String path = FileHelper.getExternalFilesDir().toString() + File.separator + CONTACTS_FILE;
  150.         File file = new File(path);
  151.         int length = (int) file.length();
  152.         byte[] bytes = new byte[length];
  153.  
  154.         try {
  155.             FileInputStream in = new FileInputStream(file);
  156.             in.read(bytes);
  157.         }
  158.         catch (Exception e1) {
  159.             Log.e(TAG, "Error restoring contact. " + e1.toString());
  160.         }
  161.         String contactString = new String(bytes);
  162.  
  163.         final ContentResolver resolver = context.getContentResolver();
  164.         final BatchOperation batchOperation = new BatchOperation(context, resolver);
  165.         final ContactOperations contactOp = ContactOperations.createBackupContact(context, batchOperation);
  166.  
  167.         String separator = System.getProperty("line.separator");
  168.  
  169.         while (contactString.length() > 0) {
  170.             int i = contactString.indexOf(separator);
  171.             String mimeType = contactString.substring(0, i);
  172.             int ii = contactString.indexOf(separator + separator);
  173.             if (ii - i < 1) {
  174.                 contactString = contactString.substring(ii + separator.length() * 2);
  175.                 continue;
  176.             }
  177.  
  178.             contactString = contactString.substring(i + separator.length());
  179.  
  180.             String data[] = new String[3];
  181.             for (int j = 0; j < 4; j++) {
  182.                 i = contactString.indexOf(separator);
  183.                 if (i == 0) {
  184.                     contactString = contactString.substring(separator.length());
  185.                     break;
  186.                 }
  187.                 data[j] = contactString.substring(0, i);
  188.                 contactString = contactString.substring(i + separator.length());
  189.             }
  190.  
  191.             contactOp.addData(data[0], data[1], data[2], mimeType);
  192.  
  193.             if (contactString.indexOf(separator) == 0)
  194.                 break;
  195.         }
  196.  
  197.         batchOperation.execute();
  198.     }
  199.  
  200.     /**
  201.      * Adds a single contact to the platform contacts provider.
  202.      *
  203.      * @param context     the Authenticator Activity context
  204.      * @param accountName the account the contact belongs to
  205.      * @param profile     the sample SyncAdapter User object
  206.      */
  207.     private static void addContact(Context context, String accountName, Profile profile, BatchOperation batchOperation) {
  208.         final ContactOperations contactOp =
  209.                 ContactOperations.createNewContact(context, accountName, batchOperation);
  210.  
  211.         contactOp.addEmail(profile.getEmail())
  212.                 .addPhone(profile.getPhone(), Phone.TYPE_MOBILE)
  213.                 .addName(profile.getGivenName(), profile.getFamilyName(), profile.getNickname())
  214. //                .addProfileAction(profileId)
  215.                 .addIMData(accountName, profile.getNickname());
  216.     }
  217.  
  218.     ...
  219.    
  220.     /**
  221.      * Updates a single contact to the platform contacts provider.
  222.      *
  223.      * @param context      the Authenticator Activity context
  224.      * @param resolver     the ContentResolver to use
  225.      * @param accountName  the account the contact belongs to
  226.      * @param user         the sample SyncAdapter contact object.
  227.      * @param rawContactId the unique Id for this rawContact in contacts
  228.      *                     provider
  229.      */
  230.     private static void updateContact(Context context,
  231.                       ContentResolver resolver,
  232.                           String accountName,
  233.                       Profile user,
  234.                       long contactId, long rawContactId,
  235.                       BatchOperation batchOperation) {
  236.         Uri uri;
  237.         String cellPhone = null;
  238.         String email = null;
  239.         String givenName = null, familyName = null, nickName = null;
  240.         String chiemoSync = null;
  241.  
  242.         boolean newEmail = true;
  243.         boolean newIM = true;
  244.  
  245.         final Cursor c = resolver.query(
  246.                 Data.CONTENT_URI,
  247.                 DataQuery.PROJECTION,
  248.                 DataQuery.SELECTION,
  249.                 new String[]{String.valueOf(rawContactId)},
  250.                 null);
  251.  
  252.         final ContactOperations contactOp = ContactOperations.updateExistingContact(context, rawContactId, batchOperation);
  253.  
  254.         try { // prepare information that needs updating
  255.             while (c.moveToNext()) {
  256.                 final long id = c.getLong(DataQuery.COLUMN_ID);
  257.                 final String mimeType = c.getString(DataQuery.COLUMN_MIMETYPE);
  258.                 uri = ContentUris.withAppendedId(Data.CONTENT_URI, id);
  259.  
  260.                 if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE)) {
  261.                     givenName = c.getString(DataQuery.COLUMN_GIVEN_NAME);
  262.                     familyName = c.getString(DataQuery.COLUMN_FAMILY_NAME);
  263.                 } else if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)) {
  264.                     final int type = c.getInt(DataQuery.COLUMN_PHONE_TYPE);
  265.  
  266.                     if (type == Phone.TYPE_MOBILE) {
  267.                         cellPhone = c.getString(DataQuery.COLUMN_PHONE_NUMBER);
  268.                         contactOp.updatePhone(cellPhone, user.getPhone(), uri);
  269.                     }
  270.                 } else if (mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
  271.                     email = c.getString(DataQuery.COLUMN_EMAIL_ADDRESS);
  272.                     if (email.equals(user.getEmail()))
  273.                         newEmail = false;
  274.                 } else if (mimeType.equals(ContactOperations.MIMETYPE_CHIEMO_CUSTOM)) {
  275.                     chiemoSync = c.getString(DataQuery.COLUMN_DATA3);
  276.                     if (user.getNickname().equals(chiemoSync.substring(chiemoSync.lastIndexOf(" "))))
  277.                         newIM = false;
  278.                 }
  279.             } // while
  280.         } finally {
  281.             c.close();
  282.         }
  283.  
  284.         // Add name, if present and not updated
  285.         if (givenName == null && familyName == null) {
  286.             contactOp.addName(user.getGivenName(), user.getFamilyName(), user.getNickname());
  287.         } else if (givenName.length() < 1 && familyName.length() < 1) {
  288.             contactOp.addName(user.getGivenName(), user.getFamilyName(), user.getNickname());
  289.         }
  290.  
  291.         // Add the phone, if present and not updated above
  292.         if (cellPhone == null)
  293.             contactOp.addPhone(user.getPhone(), Phone.TYPE_MOBILE);
  294.  
  295.         // Add the email address, if present and not updated above
  296.         if (email == null || newEmail)
  297.             contactOp.addEmail(user.getEmail());
  298.  
  299.         // Add chiemo sync, if present and not updated above
  300.         if (chiemoSync == null || newIM)
  301.             contactOp.addIMData(accountName, user.getNickname());
  302.     }
  303.  
  304.     /**
  305.      * Updates a single contact to the platform contacts provider.
  306.      *
  307.      * @param context      the Authenticator Activity context
  308.      * @param resolver     the ContentResolver to use
  309.      * @param accountName  the account the contact belongs to
  310.      * @param user         the sample SyncAdapter contact object.
  311.      * @param rawContactId the unique Id for this rawContact in contacts
  312.      *                     provider
  313.      */
  314.     private static void recreateContact(Context context, ContentResolver resolver, String accountName, Profile user, long rawContactId, BatchOperation batchOperation) {
  315.         String cellPhone = null;
  316.         String email = null;
  317.         String givenName = null, familyName = null;
  318.  
  319.         boolean newEmail = true;
  320.         boolean newPhone = true;
  321.         boolean isChiemoContact = false;
  322.  
  323.         final Cursor c = resolver.query(
  324.                 Data.CONTENT_URI,
  325.                 DataQuery.PROJECTION,
  326.                 DataQuery.SELECTION,
  327.                 new String[]{String.valueOf(rawContactId)},
  328.                 null);
  329.  
  330.         final ContactOperations contactOp = ContactOperations.createNewContact(context, accountName, batchOperation);
  331.  
  332.         try {
  333.             while (c.moveToNext()) {
  334.                 final String mimeType = c.getString(DataQuery.COLUMN_MIMETYPE);
  335.  
  336.                 switch (mimeType) {
  337.                     case StructuredName.CONTENT_ITEM_TYPE:
  338.                         givenName = c.getString(DataQuery.COLUMN_GIVEN_NAME);
  339.                         familyName = c.getString(DataQuery.COLUMN_FAMILY_NAME);
  340.                         if ((!TextUtils.isEmpty(givenName) && givenName.length() > 0) || (!TextUtils.isEmpty(familyName) && familyName.length() > 0))
  341.                             contactOp.addName(givenName, familyName, user.getNickname());
  342.                         break;
  343.                     case Phone.CONTENT_ITEM_TYPE:
  344.                         final int type = c.getInt(DataQuery.COLUMN_PHONE_TYPE);
  345.                         cellPhone = c.getString(DataQuery.COLUMN_PHONE_NUMBER);
  346.                         contactOp.addPhone(cellPhone, type);
  347.                         if (cellPhone.equals(user.getPhone()))
  348.                             newPhone = false;
  349.                         break;
  350.                     case ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE:
  351.                         email = c.getString(DataQuery.COLUMN_EMAIL_ADDRESS);
  352.                         contactOp.addEmail(email);
  353.                         if (email.equals(user.getEmail()))
  354.                             newEmail = false;
  355.                         break;
  356.                     case ContactOperations.MIMETYPE_CHIEMO_CUSTOM: {
  357.                         String data1 = c.getString(DataQuery.COLUMN_DATA1);
  358.                         String data2 = c.getString(DataQuery.COLUMN_DATA2);
  359.                         String data3 = c.getString(DataQuery.COLUMN_DATA3);
  360.                         contactOp.addData(data1, data2, data3, mimeType);
  361.                         isChiemoContact = true;
  362.                         break;
  363.                     }
  364.                     default: {
  365.                         String data1 = c.getString(DataQuery.COLUMN_DATA1);
  366.                         String data2 = c.getString(DataQuery.COLUMN_DATA2);
  367.                         String data3 = c.getString(DataQuery.COLUMN_DATA3);
  368.                         contactOp.addData(data1, data2, data3, mimeType);
  369.                         break;
  370.                     }
  371.                 }
  372.             } // while
  373.         } finally {
  374.             c.close();
  375.         }
  376.  
  377.         // Add name, if present and not updated
  378.         if (givenName == null && familyName == null) {
  379.             contactOp.addName(user.getGivenName(), user.getFamilyName(), user.getNickname());
  380.         }
  381.  
  382.         // Add the phone, if present and not updated above
  383.         if (cellPhone == null || newPhone)
  384.             contactOp.addPhone(user.getPhone(), Phone.TYPE_MOBILE);
  385.  
  386.         // Add the email address, if present and not updated above
  387.         if (email == null || newEmail)
  388.             contactOp.addEmail(user.getEmail());
  389.  
  390.         // Add chiemo sync, if present and not updated above
  391. //        if (chiemoSync == null || newIM)
  392.         if (!isChiemoContact)
  393.             contactOp.addIMData(accountName, user.getNickname());
  394.  
  395. //        if (!isChiemoContact)
  396. //            createBackupContact(context, accountName, rawContactId, batchOperation);
  397.     }
  398.  
  399.     /**
  400.      * Deletes a contact from the platform contacts provider.
  401.      *
  402.      * @param context      the Authenticator Activity context
  403.      * @param rawContactId the unique Id for this rawContact in contacts
  404.      *                     provider
  405.      */
  406.     private static void deleteContact(Context context, long rawContactId, BatchOperation batchOperation) {
  407.         batchOperation.add(ContactOperations.newDeleteCpo(
  408.                 ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), true)
  409.                 .build());
  410.     }
  411.  
  412.     /**
  413.      * Returns the RawContact id for a sample SyncAdapter contact, or 0 if the
  414.      * sample SyncAdapter user isn't found.
  415.      *
  416.      * @param profileId the sample SyncAdapter user ID to lookup
  417.      * @return the RawContact id, or 0 if not found
  418.      */
  419.     private static long lookupRawContact(ContentResolver resolver, long profileId) {
  420.         long authorId = 0;
  421.         final Cursor c = resolver.query(
  422.                 RawContacts.CONTENT_URI,
  423.                 UserIdQuery.PROJECTION,
  424.                 UserIdQuery.SELECTION,
  425.                 new String[]{String.valueOf(profileId)},
  426.                 null);
  427.         try {
  428.             if (c.moveToFirst()) {
  429.                 authorId = c.getLong(UserIdQuery.COLUMN_ID);
  430.             }
  431.         } finally {
  432.             if (c != null) {
  433.                 c.close();
  434.             }
  435.         }
  436.         return authorId;
  437.     }
  438.  
  439.     /**
  440.      * Returns the Data id for a sample SyncAdapter contact's profile row, or 0
  441.      * if the sample SyncAdapter user isn't found.
  442.      *
  443.      * @param resolver a content resolver
  444.      * @param userId   the sample SyncAdapter user ID to lookup
  445.      * @return the profile Data row id, or 0 if not found
  446.      */
  447.     private static long lookupProfile(ContentResolver resolver, long userId) {
  448.         long profileId = 0;
  449.         final Cursor c = resolver.query(
  450.                 Data.CONTENT_URI,
  451.                 ProfileQuery.PROJECTION,
  452.                 ProfileQuery.SELECTION,
  453.                 new String[]{String.valueOf(userId)},
  454.                 null);
  455.         try {
  456.             if (c != null && c.moveToFirst()) {
  457.                 profileId = c.getLong(ProfileQuery.COLUMN_ID);
  458.             }
  459.         } finally {
  460.             if (c != null) {
  461.                 c.close();
  462.             }
  463.         }
  464.         return profileId;
  465.     }
  466.  
  467.     /**
  468.      * Constants for a query to find a contact given a sample SyncAdapter user
  469.      * ID.
  470.      */
  471.     private interface ProfileQuery {
  472.         public final static String[] PROJECTION = new String[]{Data._ID};
  473.  
  474.         public final static int COLUMN_ID = 0;
  475.  
  476.         public static final String SELECTION =
  477.                 Data.MIMETYPE + "='" + ContactOperations.MIME_PROFILE + "' AND " + ContactOperations.DATA_PID + "=?";
  478.     }
  479.  
  480.     /**
  481.      * Constants for a query to find a contact given a sample SyncAdapter user
  482.      * ID.
  483.      */
  484.     private interface UserIdQuery {
  485.         public final static String[] PROJECTION = new String[]{RawContacts._ID};
  486.  
  487.         public final static int COLUMN_ID = 0;
  488.  
  489.         public static final String SELECTION = RawContacts.CONTACT_ID + "=?";
  490.     }
  491.  
  492.     /**
  493.      * Constants for a query to get contact data for a given rawContactId
  494.      */
  495.     private interface DataQuery {
  496.         public static final String[] PROJECTION =
  497.                 new String[]{Data._ID, Data.MIMETYPE, Data.DATA1, Data.DATA2, Data.DATA3};
  498.  
  499.         public static final int COLUMN_ID            = 0;
  500.         public static final int COLUMN_MIMETYPE      = 1;
  501.         public static final int COLUMN_DATA1         = 2;
  502.         public static final int COLUMN_DATA2         = 3;
  503.         public static final int COLUMN_DATA3         = 4;
  504.         public static final int COLUMN_PHONE_NUMBER  = COLUMN_DATA1;
  505.         public static final int COLUMN_PHONE_TYPE    = COLUMN_DATA2;
  506.         public static final int COLUMN_EMAIL_ADDRESS = COLUMN_DATA1;
  507.         public static final int COLUMN_EMAIL_TYPE    = COLUMN_DATA2;
  508.         public static final int COLUMN_GIVEN_NAME    = COLUMN_DATA2;
  509.         public static final int COLUMN_FAMILY_NAME   = COLUMN_DATA3;
  510.  
  511.         public static final String SELECTION = Data.RAW_CONTACT_ID + "=?";
  512.     }
  513. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement