基于android原生联系人app实现新建联系人时添加生日字段,并且插入日历提醒

联系人字段有Name,Photo,Email,Event等类型,联系人app支持新建联系人时根据这些类型扩展新的字段,添加一个Event类型的字段就可以实现添加生日信息,Event类型的字段支持设置事件的名字和事件的时间,添加好后点击就会跳到日历中
实现见FallbackAccountType.java 里的addDataKindEvent。
添加好后会显示在联系人信息的最下面,如果想显示在上面可以修改QuickContactActivity.java里的LEADING_MIMETYPES添加Event.CONTENT_ITEM_TYPE,生日信息就会和电话显示在一起。
点击生日信息会跳转到日历中,但不会在日历中插入提醒事件,如果想在生日时收到提醒通知,可以在保存联系人时插入提醒到日历
数据库中,代码在ContactSaveService.java里的updateBirthdayNotify,用日历数据库中的hasExtendedProperties字段存储这个提醒对应的联系人id,在更新联系人时更新对应的日历提醒

patch如下:

diff --git a/mediatek/proprietary/packages/apps/Contacts/AndroidManifest.xml b/mediatek/proprietary/packages/apps/Contacts/AndroidManifest.xml
index 2c5b382..1499a2a 100644
--- a/mediatek/proprietary/packages/apps/Contacts/AndroidManifest.xml
+++ b/mediatek/proprietary/packages/apps/Contacts/AndroidManifest.xml
@@ -53,6 +53,7 @@
     <uses-permission android:name="android.permission.READ_CALL_LOG"/>
     <uses-permission android:name="android.permission.READ_SMS"/>
     <uses-permission android:name="android.permission.READ_CALENDAR"/>
+    <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
     <uses-permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"/>
     <!-- Following used for Contact metadata syncing -->
     <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
diff --git a/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/ContactSaveService.java b/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/ContactSaveService.java
index 9b8d5a5..032e9a0 100644
--- a/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/ContactSaveService.java
+++ b/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/ContactSaveService.java
@@ -44,8 +44,10 @@ import android.os.Looper;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.provider.CalendarContract;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.AggregationExceptions;
+import android.provider.ContactsContract.CommonDataKinds.Event;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Contacts;
@@ -72,10 +74,12 @@ import com.android.contacts.model.CPOWrapper;
 import com.android.contacts.model.RawContactDelta;
 import com.android.contacts.model.RawContactDeltaList;
 import com.android.contacts.model.RawContactModifier;
+import com.android.contacts.model.ValuesDelta;
 import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.preference.ContactsPreferences;
 import com.android.contacts.util.ContactDisplayUtils;
 import com.android.contacts.util.ContactPhotoUtils;
+import com.android.contacts.util.DateUtils;
 import com.android.contacts.util.PermissionsUtil;
 import com.android.contactsbind.FeedbackHelper;
 
@@ -86,7 +90,9 @@ import com.mediatek.contacts.ContactSaveServiceEx;
 import com.mediatek.contacts.util.Log;
 
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Collection;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -557,6 +563,84 @@ public class ContactSaveService extends IntentService {
         }
         return serviceIntent;
     }
+    
+    // fangao cyj add for contact birthday start
+    private void updatecalendar(final long rawContactId, String datestr, String title) {
+        long date = 0;
+        boolean everyYear = false;
+        if (datestr != null) {
+            everyYear = datestr.startsWith("--");
+            final Calendar cal = DateUtils.parseDate(datestr, false);
+            if (cal != null) {
+                final Date nextAnniversary = DateUtils.getNextAnnualDate(cal);
+                date = nextAnniversary.getTime();
+            }
+        }
+        long hasExtendedProperties = rawContactId + 100;
+        Intent i = new Intent("fangao.intent.action.BIRTHDAY_NOTIFY");
+        i.setPackage("com.android.providers.calendar");
+        i.putExtra("contactId", hasExtendedProperties);
+        i.putExtra("date", date);
+        i.putExtra("title", title);
+        i.putExtra("everyYear", everyYear);
+        sendBroadcast(i);
+    }
+    
+    private void updateBirthdayNotify(RawContactDeltaList states, final long rawContactId) {
+        for (RawContactDelta delta : states) {
+            ArrayList<ValuesDelta> vds = delta.getMimeEntries(Event.CONTENT_ITEM_TYPE);
+            if (vds != null) {
+                for (ValuesDelta vd : vds) {
+                        boolean isChange = false;
+                        // date change
+                        ContentValues before = vd.getBefore();
+                        ContentValues after = vd.getAfter();
+                        if ((before == null && after != null)||(after == null && before != null)) isChange = true;
+                        else if(after != null && before != null) {
+                            Object newValue = after.get(Event.START_DATE);
+                            Object oldValue = before.get(Event.START_DATE);
+                             if(newValue != null && oldValue != null && !oldValue.equals(newValue)) isChange = true;
+                        }
+                        // name change
+                        StringBuilder atitle = new StringBuilder("");
+                        StringBuilder btitle = new StringBuilder("");
+                        ArrayList<ValuesDelta> namevds = delta.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
+                        if (namevds != null && namevds.size() > 0) {
+                            ContentValues ncvaf = namevds.get(0).getAfter();
+                            ContentValues ncvbe = namevds.get(0).getBefore();
+                            String daname = ncvaf != null?ncvaf.getAsString(StructuredName.DISPLAY_NAME):null;
+                            String dbname = ncvbe != null?ncvbe.getAsString(StructuredName.DISPLAY_NAME):null;
+                            if (daname != null) atitle.append(daname);
+                            if (dbname != null) btitle.append(dbname);
+                            String ganame = ncvaf != null?ncvaf.getAsString(StructuredName.GIVEN_NAME):null;
+                            String gbname = ncvbe != null?ncvbe.getAsString(StructuredName.GIVEN_NAME):null;
+                            if (ganame != null && atitle.length()==0) atitle.append(ganame);
+                            if (gbname != null && btitle.length()==0) btitle.append(gbname);
+                              String faname = ncvaf != null?ncvaf.getAsString(StructuredName.FAMILY_NAME):null;
+                            String fbname = ncvbe != null?ncvbe.getAsString(StructuredName.FAMILY_NAME):null;
+                            if (faname != null && atitle.length()==0) atitle.append(faname);
+                            if (fbname != null && btitle.length()==0) btitle.append(fbname);
+                            
+                            if (!atitle.toString().equals(btitle.toString())) isChange = true;
+                            
+                            atitle.append("的生日");
+                        }
+                        
+                        if (isChange) {
+                            String data = null;
+                            if (after != null) {
+                                data = after.getAsString(Event.START_DATE);
+                                if (data == null) {
+                                    data = before == null?null:before.getAsString(Event.START_DATE);
+                                }
+                            }
+                            updatecalendar(rawContactId, data, atitle.toString());
+                        }
+                }
+            }
+        }
+    }
+    // fangao cyj add for contact birthday end
 
     private void saveContact(Intent intent) {
         RawContactDeltaList state = intent.getParcelableExtra(EXTRA_CONTACT_STATE);
@@ -625,6 +709,13 @@ public class ContactSaveService extends IntentService {
                 if (rawContactId == -1) {
                     throw new IllegalStateException("Could not determine RawContact ID after save");
                 }
+                // fangao start
+                try {
+                    updateBirthdayNotify(state, rawContactId);
+                } catch(Exception e) {
+                    Log.e(TAG, "updateBirthdayNotify error:"+e);
+                }
+                // fangao end
                 // We don't have to check to see if the value is still -1.  If we reach here,
                 // the previous loop iteration didn't succeed, so any ID that we obtained is bogus.
                 insertedRawContactId = getInsertedRawContactId(diffWrapper, results);
diff --git a/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/model/account/FallbackAccountType.java b/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/model/account/FallbackAccountType.java
index dd2f15c..bbc4105 100644
--- a/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/model/account/FallbackAccountType.java
+++ b/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/model/account/FallbackAccountType.java
@@ -22,16 +22,24 @@
 package com.android.contacts.model.account;
 
 import android.accounts.AuthenticatorDescription;
+import android.content.ContentValues;
 import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.provider.ContactsContract.CommonDataKinds.Event;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.content.res.ResourcesCompat;
 
 import com.android.contacts.R;
+import com.android.contacts.model.account.AccountType.DefinitionException;
+import com.android.contacts.model.account.AccountType.EditField;
+import com.android.contacts.model.account.BaseAccountType.EventActionInflater;
+import com.android.contacts.model.account.BaseAccountType.SimpleInflater;
+import com.android.contacts.model.account.BaseAccountType.Weight;
 import com.android.contacts.model.dataitem.DataKind;
+import com.android.contacts.util.CommonDateUtils;
 import com.android.contactsbind.FeedbackHelper;
-
+import com.google.common.collect.Lists;
 import com.mediatek.contacts.util.Log;
 
 public class FallbackAccountType extends BaseAccountType {
@@ -62,12 +70,40 @@ public class FallbackAccountType extends BaseAccountType {
             addDataKindWebsite(context);
             addDataKindSipAddress(context);
             addDataKindGroupMembership(context);
+            addDataKindEvent(context);// fangao cyj add for contacts birthday
 
             mIsInitialized = true;
         } catch (DefinitionException e) {
             FeedbackHelper.sendFeedback(context, TAG, "Failed to build fallback account type", e);
         }
     }
+    
+    // fangao cyj add for contacts birthday start
+    private DataKind addDataKindEvent(Context context) throws DefinitionException {
+        DataKind kind = addKind(new DataKind(Event.CONTENT_ITEM_TYPE,
+                    R.string.eventLabelsGroup, Weight.PHONE, true));
+        kind.actionHeader = new EventActionInflater();
+        kind.actionBody = new SimpleInflater(Event.START_DATE);
+
+        kind.typeColumn = Event.TYPE;
+        kind.typeList = Lists.newArrayList();
+        kind.dateFormatWithoutYear = CommonDateUtils.NO_YEAR_DATE_FORMAT;
+        kind.dateFormatWithYear = CommonDateUtils.FULL_DATE_FORMAT;
+        kind.typeList.add(buildEventType(Event.TYPE_BIRTHDAY, true).setSpecificMax(1));
+//        kind.typeList.add(buildEventType(Event.TYPE_ANNIVERSARY, false));
+//        kind.typeList.add(buildEventType(Event.TYPE_OTHER, false));
+//        kind.typeList.add(buildEventType(Event.TYPE_CUSTOM, false).setSecondary(true)
+//                .setCustomColumn(Event.LABEL));
+
+        kind.defaultValues = new ContentValues();
+        kind.defaultValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Event.DATA, R.string.eventLabelsGroup, FLAGS_EVENT));
+
+        return kind;
+    }
+    // fangao cyj add for contacts birthday end
 
     @Override
     public Drawable getDisplayIcon(Context context) {
diff --git a/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/quickcontact/QuickContactActivity.java b/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 6c03f9f..1b2bcab 100644
--- a/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/mediatek/proprietary/packages/apps/Contacts/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -355,7 +355,7 @@ public class QuickContactActivity extends ContactsActivity {
      */
     private static final List<String> LEADING_MIMETYPES = Lists.newArrayList(
             Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE,
-            StructuredPostal.CONTENT_ITEM_TYPE);
+            StructuredPostal.CONTENT_ITEM_TYPE,Event.CONTENT_ITEM_TYPE); // fangao cyj add Event show birthday on the top
 
     private static final List<String> SORTED_ABOUT_CARD_MIMETYPES = Lists.newArrayList(
             Nickname.CONTENT_ITEM_TYPE,
@@ -363,7 +363,6 @@ public class QuickContactActivity extends ContactsActivity {
             // No mimetype for phonetic name exists.
             Website.CONTENT_ITEM_TYPE,
             Organization.CONTENT_ITEM_TYPE,
-            Event.CONTENT_ITEM_TYPE,
             Relation.CONTENT_ITEM_TYPE,
             Im.CONTENT_ITEM_TYPE,
             GroupMembership.CONTENT_ITEM_TYPE,
@@ -1794,8 +1793,17 @@ public class QuickContactActivity extends ContactsActivity {
                         event.getLabel()).toString();
             }
             text = DateUtils.formatDate(context, dataString);
+            // fangao cyj add for contact birthday start
+            header = text;
+            text = subHeader;
+            subHeader = null;
+            // fangao cyj add for contact birthday end
             entryContextMenuInfo = new EntryContextMenuInfo(text, header,
                     dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
+            // fangao cyj add for contact birthday start
+            iconResourceId = R.drawable.quantum_ic_event_vd_theme_24;
+            icon = res.getDrawable(iconResourceId);
+            // fangao cyj add for contact birthday end
         } else if (dataItem instanceof RelationDataItem) {
             final RelationDataItem relation = (RelationDataItem) dataItem;
             final String dataString = relation.buildDataStringForDisplay(context, kind);
diff --git a/mediatek/proprietary/packages/providers/CalendarProvider/AndroidManifest.xml b/mediatek/proprietary/packages/providers/CalendarProvider/AndroidManifest.xml
index 907587a..3d683d9 100755
--- a/mediatek/proprietary/packages/providers/CalendarProvider/AndroidManifest.xml
+++ b/mediatek/proprietary/packages/providers/CalendarProvider/AndroidManifest.xml
@@ -118,6 +118,12 @@
                 <action android:name="com.mediatek.intent.action.SETTINGS_PACKAGE_DATA_CLEARED" />
             </intent-filter>
         </receiver>
+       <!-- fangao cyj add update calendar when add contact birthday -->
+       <receiver android:name="BirthdayNotifyReceiver">
+           <intent-filter>
+               <action android:name="fangao.intent.action.BIRTHDAY_NOTIFY"/>
+           </intent-filter>
+       </receiver>
 
     </application>
 </manifest>
diff --git a/mediatek/proprietary/packages/providers/CalendarProvider/src/com/android/providers/calendar/BirthdayNotifyReceiver.java b/mediatek/proprietary/packages/providers/CalendarProvider/src/com/android/providers/calendar/BirthdayNotifyReceiver.java
new file mode 100755
index 0000000..6dd7e10
--- /dev/null
+++ b/mediatek/proprietary/packages/providers/CalendarProvider/src/com/android/providers/calendar/BirthdayNotifyReceiver.java
@@ -0,0 +1,113 @@
+
+
+package com.android.providers.calendar;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.provider.CalendarContract;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * fangao cyj add for contact birthday
+ */
+public class BirthdayNotifyReceiver extends BroadcastReceiver {
+    private static final String TAG = "BirthdayNotifyReceiver";
+    static final String SCHEDULE = "com.android.providers.calendar.SCHEDULE_ALARM";
+
+    private final ExecutorService executor = Executors.newCachedThreadPool();
+    private PowerManager.WakeLock mWakeLock;
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        try {
+            long contactId = intent.getLongExtra("contactId", -1);
+            long date = intent.getLongExtra("date", -1);
+            String title = intent.getStringExtra("title");
+            boolean everyYear = intent.getBooleanExtra("everyYear", false);
+            if (contactId != -1 && date != -1 && title != null) {
+                updatecalendar(context, contactId, date, title, everyYear);
+            }
+        } catch(Exception e) {
+            Log.e(TAG, "BirthdayNotifyReceiver updatecalendar  error:"+e);
+        }
+
+    }
+    
+    private void updatecalendar(Context context, final long hasExtendedProperties, long date, String title, boolean everyYear) {
+        // delete first
+        Cursor cur = null;
+        ContentResolver cr = context.getContentResolver();
+        Uri uri = CalendarContract.Events.CONTENT_URI;
+        String[] EVENT_PROJECTION = new String[]{
+                CalendarContract.Events._ID
+        };
+        String selection = "(" + CalendarContract.Events.HAS_EXTENDED_PROPERTIES + " = ?)";
+        String[] selectionArgs = new String[]{String.valueOf(hasExtendedProperties)};
+        cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
+        ArrayList<Long> events = new ArrayList<>();
+        while (cur.moveToNext()) {
+            events.add(cur.getLong(0));
+        }
+        for(Long eventId : events) {
+            selection = "(" + CalendarContract.Events._ID + " = ?)";
+            selectionArgs = new String[]{String.valueOf(eventId)};
+            cr.delete(uri, selection, selectionArgs);
+            
+            selection = "(" + CalendarContract.Reminders.EVENT_ID + " = ?)";
+            selectionArgs = new String[]{String.valueOf(eventId)};
+            cr.delete(CalendarContract.Reminders.CONTENT_URI, selection, selectionArgs);
+        }
+        // insert
+        if (date != 0) {
+            long daymillis = 24*3600*1000;
+            ContentValues values = new ContentValues();
+            values.put(CalendarContract.Events.HAS_EXTENDED_PROPERTIES, hasExtendedProperties); // Contactid
+            values.put(CalendarContract.Events.CALENDAR_ID, 1);
+            values.put(CalendarContract.Events.DTSTART, date);
+            values.put(CalendarContract.Events.TITLE, title);
+            //values.put(CalendarContract.Events.DESCRIPTION, calender.description);
+            //values.put(CalendarContract.Events.EVENT_LOCATION, calender.eventLocation);
+            values.put(CalendarContract.Events.EVENT_TIMEZONE, "UTC");
+            values.put(CalendarContract.Events.ACCESS_LEVEL, 0);
+            values.put(CalendarContract.Events.ALL_DAY, 1);
+            values.put(CalendarContract.Events.ORGANIZER, "PC Sync");
+            values.put(CalendarContract.Events.STATUS, 1);
+
+            if (everyYear) {
+                values.put(CalendarContract.Events.DURATION, "P1D"); // every year
+                values.put(CalendarContract.Events.RRULE, "FREQ=YEARLY;WKST=SU"); // every year
+            } else {
+                values.put(CalendarContract.Events.DTEND, date+daymillis);
+                values.put(CalendarContract.Events.LAST_DATE, date+daymillis);
+            }
+            
+            // add Reminder
+            values.put(CalendarContract.Events.HAS_ALARM, 1);
+            
+            Uri eventUri = cr.insert(uri, values);
+            
+            // get the event ID that is the last element in the Uri
+            long eventID = Long.parseLong(eventUri.getLastPathSegment());
+
+            // add Reminder
+            ContentValues reminderValues = new ContentValues();
+            reminderValues.put(CalendarContract.Reminders.EVENT_ID, eventID);
+            reminderValues.put(CalendarContract.Reminders.MINUTES, 12*60);// 提前XXXX有提醒
+            reminderValues.put(CalendarContract.Reminders.METHOD, 1);// 提醒方式
+
+            cr.insert(CalendarContract.Reminders.CONTENT_URI, reminderValues);
+        }
+        
+    }
+
+}

效果如下:

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页