Android中删除常用联系人

来源:互联网 发布:速卖通采集软件 编辑:程序博客网 时间:2024/06/07 06:11
在Android 4.0中,google已经把移除常用联系人这个功能去掉。
当用户在进行拨打电话,接听电话等电话行为时,系统会自动对其对应号码的使用进行计数。然后根据计数情况来显示常用联系人。 移除常用联系人只是指把该联系人从常用联系人列表移除。
移除常用联系人基本思想是:在数据库中,保留goolge原来中用对通话进行计数的字段DataUsageStatColumns.TIMES_USED ,新增加一个字段DataUsageStatColumns.FAKE_TIMES_USED来对通话进行计数,并提供一些对该字段操作接口,然后根据我们DataUsageStatColumns.FAKE_TIMES_USED计数情况来显示常用联系人
移除常用联系该功能的实现主要分为两个部分:
第一当用户从Call log删除一个通话记录,表明用户不想和该联系人的该通话记录本看到,因此应该把该联系人从常用联系人列表中移除。
第二用户可以从常用联系人列表中移除一个联系人,同时把和该联系人相关的Call log记录都删除掉。
添加移除常用联系功能,需要修改两个应用程序的源码,一个是com.android.providers.contacts,另一个是com.android.contacts
。在MTK6575平台上,对于应用com.android.providers.contacts改动的文件有

packages/providers/ContactsProvider/src/com/android/providers/contacts/CallLogProvider.java
packages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsProvider2.java
packages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsDatabaseHelper.java

主要修改如下:
文件packages/providers/ContactsProvider/src/com/android/providers/contacts/CallLogProvider.java

@@ -127,7 +132,22 @@ public class CallLogProvider extends ContentProvider {
         sCallsProjectionMap.put(Calls.DATA_ID, Calls.DATA_ID);
         /* The previous lines are provided and maintained by Mediatek inc.*/
     }
+    private static final HashMap<String, String> sCallsToJoin_USAGE_STAT_ProjectionMap;
+    static {
+        /*Calls projection map*/
+        sCallsToJoin_USAGE_STAT_ProjectionMap = new HashMap<String, String>();
+        sCallsToJoin_USAGE_STAT_ProjectionMap.put(Calls._ID, Tables.CALLS + "._id as " + Calls._ID);
+        sCallsToJoin_USAGE_STAT_ProjectionMap.put(Calls.NUMBER, Calls.NUMBER);
+        sCallsToJoin_USAGE_STAT_ProjectionMap.put(Calls.DATE, Calls.DATE);
+        sCallsToJoin_USAGE_STAT_ProjectionMap.put(Calls.DURATION, Calls.DURATION);
+        sCallsToJoin_USAGE_STAT_ProjectionMap.put(Calls.TYPE, Calls.TYPE);
+        /* The fillowing lines are provided and maintained by Mediatek inc.*/
+        sCallsToJoin_USAGE_STAT_ProjectionMap.put(Calls.SIM_ID, Calls.SIM_ID);
+        sCallsToJoin_USAGE_STAT_ProjectionMap.put(Calls.RAW_CONTACT_ID, Calls.RAW_CONTACT_ID);
+        sCallsToJoin_USAGE_STAT_ProjectionMap.put(Calls.DATA_ID, Calls.DATA_ID);
+        /* The previous lines are provided and maintained by Mediatek inc.*/
+    }
     private static final String mstableCallsJoinData = Tables.CALLS + " LEFT JOIN " 
     + " (SELECT * FROM " +  Views.DATA + " WHERE " + Data._ID + " IN "
     + "(SELECT " +  Calls.DATA_ID + " FROM " + Tables.CALLS + ")) AS " + Views.DATA
@@ -605,7 +625,7 @@ public class CallLogProvider extends ContentProvider {
         return getDatabaseModifier(db).update(Tables.CALLS, values, selectionBuilder.build(),
                 selectionArgs);
     }
-
+    IContentProvider mContentProvider;
     @Override
     public int delete(Uri uri, String selection, String[] selectionArgs) {
         SelectionBuilder selectionBuilder = new SelectionBuilder(selection);
@@ -640,7 +660,31 @@ public class CallLogProvider extends ContentProvider {
          *       selectionBuilder.build(), selectionArgs);
          */
         case CALLS: {
-            int count = 0;
+              ArrayList<Long> idList=new ArrayList<Long> ();
+              ArrayList<Integer> typeList=new ArrayList<Integer> ();
+              
+              Cursor c = db.query(true,
+                    Tables.CALLS, new String[] { Calls._ID, Calls.DATA_ID,Calls.TYPE},
+                    selection, selectionArgs,null,null,null,null);
+              long id=-1;
+              if(c.moveToFirst())
+              {
+                      do
+                      {
+                              id=c.getLong(1);
+                              if(id>0)
+                              {
+                                     idList.add(id);
+                                     typeList.add(c.getInt(2));
+                              }
+                              
+                      }while(c.moveToNext());
+              }
+              long ids[]=new long[idList.size()];
+              for(int i=0;i<ids.length;i++)
+                      ids[i]=idList.get(i);
+              c.close();
+             int count = 0;
             if (FeatureOption.MTK_SEARCH_DB_SUPPORT == true) {
               /* 
                * update name_lookup for usage of dialer search:
@@ -788,6 +832,36 @@ public class CallLogProvider extends ContentProvider {
             if (count > 0) {
               notifyDialerSearchChange();
             }
+            if(ids.length>0&&uri.getBooleanQueryParameter("updateFakeTimesUsed", true))
+            {
+                              IContentProvider cp = null;
+                   synchronized (this) {
+                       cp = mContentProvider;
+                       if (cp == null) {
+                           cp = mContentProvider = getContext().getContentResolver().acquireProvider(ContactsContract.AUTHORITY);
+                       }
+                   }
+                try {
+                      Bundle bundle=new Bundle();
+                      bundle.putLongArray("dataIds", ids);
+                      //bundle.putIntArray("types", types);
+                      //bundle.putIntArray("counts", counts);
+                    Bundle b = cp.call(ContactsProvider2.CALL_METHOD_UPDATE_FAKE_TIMES_USED, "Asynchronous", bundle);
+                    /*if (b != null) {
+                        int v = b.getInt("count",0);
+                        if(v!=count)
+                        {
+                              Log.e(TAG, "some erro happpend in CALL_METHOD_UPDATE_FAKE_TIMES_USED");
+                        }
+                    }*/
+                    // If the response Bundle is null, we fall through
+                    // to the query interface below.
+                } catch (RemoteException e) {
+                   Log.w(TAG, "", e);
+                    // Not supported by the remote side?  Fall through
+                    // to query().
+                }
+            }
             return count;
         }

文件packages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsDatabaseHelper.java

@@ -733,7 +733,12 @@ import com.mediatek.providers.contacts.ContactsFeatureConstants.FeatureOption;
         public static final String TIMES_USED = "times_used";
         public static final String CONCRETE_TIMES_USED =
                 Tables.DATA_USAGE_STAT + "." + TIMES_USED;
-
+        /** type: INTEGER */
+        public static final String FAKE_TIMES_USED = "fake_times_used";
+        public static final String CONCRETE_FAKE_TIMES_USED =
+                Tables.DATA_USAGE_STAT + "." + FAKE_TIMES_USED;
+        /*add by Robin Hu*/
         /** type: INTEGER */
         public static final String USAGE_TYPE_INT = "usage_type";
         public static final String CONCRETE_USAGE_TYPE =
@@ -1383,6 +1388,7 @@ import com.mediatek.providers.contacts.ContactsFeatureConstants.FeatureOption;
                 DataUsageStatColumns.DATA_ID + " INTEGER NOT NULL, " +
                 DataUsageStatColumns.USAGE_TYPE_INT + " INTEGER NOT NULL DEFAULT 0, " +
                 DataUsageStatColumns.TIMES_USED + " INTEGER NOT NULL DEFAULT 0, " +
+                DataUsageStatColumns.FAKE_TIMES_USED + " INTEGER NOT NULL DEFAULT 0, " +
                 DataUsageStatColumns.LAST_TIME_USED + " INTERGER NOT NULL DEFAULT 0, " +
                 "FOREIGN KEY(" + DataUsageStatColumns.DATA_ID + ") REFERENCES "
                         + Tables.DATA + "(" + Data._ID + ")" +
@@ -1918,6 +1924,7 @@ import com.mediatek.providers.contacts.ContactsFeatureConstants.FeatureOption;
                 + MimetypesColumns.CONCRETE_MIMETYPE + " AS " + Data.MIMETYPE + ", "
                 + DataUsageStatColumns.USAGE_TYPE_INT + ", "
                 + DataUsageStatColumns.TIMES_USED + ", "
+                + DataUsageStatColumns.FAKE_TIMES_USED + ", "
                 + DataUsageStatColumns.LAST_TIME_USED
                 + " FROM " + Tables.DATA_USAGE_STAT
                 + " JOIN " + Tables.DATA + " ON ("

 文件packages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsProvider2.java

@@ -261,8 +264,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
      * the total times contacted. See also {@link #sStrequentFrequentProjectionMap}.
      */
     private static final String TIMES_USED_SORT_COLUMN = "times_used_sort";
-
-    private static final String FREQUENT_ORDER_BY = DataUsageStatColumns.TIMES_USED + " DESC,"
+    private static final String FREQUENT_ORDER_BY = DataUsageStatColumns.FAKE_TIMES_USED + " DESC,"
             + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
     /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE =
@@ -745,7 +747,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
     private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder()
             .addAll(sContactsProjectionMap)
-            .add(TIMES_USED_SORT_COLUMN, "SUM(" + DataUsageStatColumns.CONCRETE_TIMES_USED + ")")
+            .add(TIMES_USED_SORT_COLUMN, "SUM(" + DataUsageStatColumns.CONCRETE_FAKE_TIMES_USED + ")")
             .build();
      /**
@@ -771,7 +773,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
     private static final ProjectionMap sStrequentPhoneOnlyFrequentProjectionMap
             = ProjectionMap.builder()
             .addAll(sContactsProjectionMap)
-            .add(TIMES_USED_SORT_COLUMN, DataUsageStatColumns.CONCRETE_TIMES_USED)
+            //.add(TIMES_USED_SORT_COLUMN, DataUsageStatColumns.CONCRETE_TIMES_USED)
+            .add(TIMES_USED_SORT_COLUMN, DataUsageStatColumns.CONCRETE_FAKE_TIMES_USED)
             .add(Phone.NUMBER)
             .add(Phone.TYPE)
             .add(Phone.LABEL)
@@ -2218,7 +2221,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
      @Override
     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        if (mWriteAccessLatch != null) {
+       if (mWriteAccessLatch != null) {
             // We are stuck trying to upgrade contacts db.  The only update request
             // allowed in this case is an update of provider status, which will trigger
             // an attempt to upgrade contacts again.
@@ -2295,7 +2298,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
     /* package */ void substituteDb(SQLiteDatabase db) {
         mActiveDb.set(db);
     }
-
+Handler handler=new Handler();
     @Override
     public Bundle call(String method, String arg, Bundle extras) {
         waitForAccess(mReadAccessLatch);
@@ -2315,6 +2318,72 @@ public class ContactsProvider2 extends AbstractContactsProvider
             response.putParcelable(Authorization.KEY_AUTHORIZED_URI, authUri);
             return response;
         }
+        else if (CALL_METHOD_UPDATE_FAKE_TIMES_USED.equals(method)) {
+              String strUri=extras.getString("Uri");
+              if(strUri==null)
+              {
+                  final long[] dataIds= extras.getLongArray("dataIds");
+                  //final int[] types=extras.getIntArray("types");
+                  //final int [] counts=extras.getIntArray("counts");
+                  if("Asynchronous".equals(arg))
+                  {
+                        Runnable r=new Runnable()
+                        {
+
+                                     @Override
+                                     public void run() {
+                                             // TODO Auto-generated method stub
+                                             for(int i=0;i<dataIds.length;i++)
+                                             update_FAKE_TIMES_USED_Stat(dataIds[i],ID_TYPE_VIEW_DATA,false);
+                                     }};
+                                     handler.postDelayed(r, 10);
+                                     return null;
+                  }
+                  else
+                  {
+                         int count=0;
+                         for(int i=0;i<dataIds.length;i++)
+                                 count+= update_FAKE_TIMES_USED_Stat(dataIds[i],ID_TYPE_VIEW_DATA,false);
+                         Bundle response = new Bundle();
+                         response.putInt("count", count);
+                         return response;
+                  }
+              }
+              else
+              {
+                      Uri uri=Uri.parse(strUri);
+                int match = sUriMatcher.match(uri);
+                match = processMatchEx(match, uri);
+                int count=-1;
+                List<String> pathSegments = uri.getPathSegments();
+                if(match==CONTACTS_LOOKUP_ID)
+                {
+                      int type=ID_TYPE_VIEW_DATA;
+                      if(arg!=null)
+                      {
+                              if(arg.equals("ID_TYPE_CONTACT"))
+                                     type=ID_TYPE_CONTACT;
+                              else if(arg.equals("ID_TYPE_RAW_CONTACT"))
+                              {
+                                     type=ID_TYPE_RAW_CONTACT;
+                              }
+                      }
+                    long id = Long.parseLong(pathSegments.get(3));
+                    count= update_FAKE_TIMES_USED_Stat(id,type,true);    
+                }
+                /*else if(match==CONTACTS_LOOKUP)
+                {
+                      String contactLookupKey = pathSegments.get(2);
+                      count= update_FAKE_TIMES_USED_Stat(contactLookupKey);
+                }*/
+                if(count!=-1)
+                {
+                      Bundle response = new Bundle();
+                      response.putInt("count", count);
+                      return response;
+                }
+              }
+       }
         return null;
     }
 
@@ -5515,7 +5584,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
                 // UNION ALL
                 // (SQL for listing frequently contacted items)
                 // ORDER BY ...
-
+              
                 final boolean phoneOnly = readBooleanQueryParameter(
                         uri, ContactsContract.STREQUENT_PHONE_ONLY, false);
                 if (match == CONTACTS_STREQUENT_FILTER && uri.getPathSegments().size() > 3) {
@@ -5569,7 +5638,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
                             + " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "="
                                 + DataColumns.CONCRETE_ID + " AND "
                             + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "="
-                                + DataUsageStatColumns.USAGE_TYPE_INT_CALL + ")");
+                                + DataUsageStatColumns.USAGE_TYPE_INT_CALL 
+                                + " AND "+DataUsageStatColumns.CONCRETE_FAKE_TIMES_USED+">0"+")");
                     appendContactPresenceJoin(tableBuilder, projection, RawContacts.CONTACT_ID);
                     appendContactStatusUpdateJoin(tableBuilder, projection,
                             ContactsColumns.LAST_STATUS_UPDATE_ID);
@@ -6955,7 +7025,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
         if (includeDataUsageStat) {
             sb.append(" ON (" +
                     DbQueryUtils.concatenateClauses(
-                            DataUsageStatColumns.CONCRETE_TIMES_USED + " > 0",
+                            DataUsageStatColumns.CONCRETE_FAKE_TIMES_USED + " > 0",
                             RawContacts.CONTACT_ID + "=" + Views.CONTACTS + "." + Contacts._ID) +
                     ")");
         }
@@ -8431,7 +8501,6 @@ public class ContactsProvider2 extends AbstractContactsProvider
 
         return successful;
     }
-
     /**
      * Update {@link Tables#DATA_USAGE_STAT}.
      *
@@ -8444,7 +8513,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
         final String where = DataUsageStatColumns.DATA_ID + " =? AND "
                 + DataUsageStatColumns.USAGE_TYPE_INT + " =?";
         final String[] columns =
-                new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.TIMES_USED };
+                new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.TIMES_USED, DataUsageStatColumns.FAKE_TIMES_USED };
         final ContentValues values = new ContentValues();
         for (Long dataId : dataIds) {
             final String[] args = new String[] { dataId.toString(), String.valueOf(typeInt) };
@@ -8460,6 +8529,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
                         } else {
                             values.clear();
                             values.put(DataUsageStatColumns.TIMES_USED, cursor.getInt(1) + 1);
+                            values.put(DataUsageStatColumns.FAKE_TIMES_USED, cursor.getInt(2) + 1);
                             values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis);
                             mActiveDb.get().update(Tables.DATA_USAGE_STAT, values,
                                     DataUsageStatColumns._ID + " =?",
@@ -8470,6 +8540,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
                         values.put(DataUsageStatColumns.DATA_ID, dataId);
                         values.put(DataUsageStatColumns.USAGE_TYPE_INT, typeInt);
                         values.put(DataUsageStatColumns.TIMES_USED, 1);
+                        values.put(DataUsageStatColumns.FAKE_TIMES_USED, 1);
                         values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis);
                         mActiveDb.get().insert(Tables.DATA_USAGE_STAT, null, values);
                     }
@@ -8484,7 +8555,213 @@ public class ContactsProvider2 extends AbstractContactsProvider
 
         return dataIds.size();
     }
+    /**
+     * Update {@link Tables#DATA_USAGE_STAT}.
+     *
+     * @return the number of rows affected.
+     */
+     final int update_FAKE_TIMES_USED_Stat(
+            long dataIds[]) 
+    {
+       return update_FAKE_TIMES_USED_Stat(dataIds,null,null);
+    }
+    /* package */ int update_FAKE_TIMES_USED_Stat(
+            long dataIds[], int types[], int  counts[]) {
+        //int typeInt;
+        /*final String where = DataUsageStatColumns.DATA_ID + " =? AND "
+                + DataUsageStatColumns.USAGE_TYPE_INT + " ="+DataUsageStatColumns.USAGE_TYPE_INT_CALL;*/
+        final String where = DataUsageStatColumns.DATA_ID + " =?";
+       
+        final String[] columns =
+                new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.FAKE_TIMES_USED };
+        final ContentValues values = new ContentValues();
+        int n=0;
+        int i=0;
+        long dataId=0;
+        if(mActiveDb.get()==null)
+              mActiveDb.set(mContactsHelper.getWritableDatabase());
+        for (i=0; i<dataIds.length;i++) {
+              dataId=dataIds[i];
+              //typeInt = types[i];
+              //typeInt = sDataUsageTypeMap.get(types[i]);
+            final String[] args = new String[] { dataId+""};
+            mActiveDb.get().beginTransaction();
+            try {
+                final Cursor cursor = mActiveDb.get().query(Tables.DATA_USAGE_STAT, columns, where,
+                        args, null, null, null);
+                try {
+                    if (cursor.getCount() > 0) {
+                        if (!cursor.moveToFirst()) {
+                            Log.e(TAG,
+                                    "moveToFirst() failed while getAccount() returned non-zero.");
+                        } else {
+                              
+                              //n=cursor.getInt(1) + counts[i];
+                              n=0;//force clear
+                              do{
+                            values.clear();
+                            values.put(DataUsageStatColumns.FAKE_TIMES_USED,n);
+                            mActiveDb.get().update(Tables.DATA_USAGE_STAT, values,
+                                    DataUsageStatColumns._ID + " =?",
+                                    new String[] { cursor.getString(0) });
+                              }while(cursor.moveToNext());
+                        }
+                    } else {
+                      Log.wtf(TAG, "warning!There is no record for dataId=="+dataId+" and Type=="+DataUsageStatColumns.USAGE_TYPE_INT_CALL);
+                    }
+                    mActiveDb.get().setTransactionSuccessful();
+                } finally {
+                    cursor.close();
+                }
+            } finally {
+                mActiveDb.get().endTransaction();
+            }
+        }
+        notifyChange();
+        return dataIds.length;
+    }
+    
+    final static String CALL_METHOD_UPDATE_FAKE_TIMES_USED="CALL_METHOD_update_FAKE_TIMES_USED_Stat";
+    final static String VIEWS_DATA_ID="_id";
+    final static int ID_TYPE_VIEW_DATA=0;
+    final static int ID_TYPE_CONTACT=1;
+    final static int ID_TYPE_RAW_CONTACT=2;
+    int update_FAKE_TIMES_USED_Stat(long id,int type,boolean needDeleteCallLog) {
+       long contactId=0;
+              Uri uri=null;
+        Cursor cursor=null;
+        String projects[]=null;
+       String selection=null;
+       String[] selectionArgs=null;
+       if(type==ID_TYPE_VIEW_DATA||type==ID_TYPE_RAW_CONTACT)
+       {
+              uri=Data.CONTENT_URI;
+            cursor=null;
+            projects=new String[]{Data.CONTACT_ID};
+            if(type==ID_TYPE_RAW_CONTACT)
+              {
+              selection=Data.RAW_CONTACT_ID+" = "+id;
+              }
+            else
+            {
+              selection=Data._ID+" = "+id;
+            }
+              selectionArgs=null;
+              try {
+                  cursor=getContext().getContentResolver().query(uri,projects,selection,selectionArgs,null);
+                      if (cursor.getCount() > 0) {
+                              cursor.moveToFirst();
+                              contactId=cursor.getLong(0);
+                      } else {
+                              Log.wtf(TAG, "warning!There is no record for rawContactId="+id);
+                              return 0;
+                      }
+              } finally {
+                      if(cursor!=null)
+                  cursor.close();
+              } 
+       }
 
+       else if(type==ID_TYPE_CONTACT)
+       {
+              contactId=id;
+              
+       }
+       return update_FAKE_TIMES_USED_Stat(contactId,needDeleteCallLog);
+    }
+    final int update_FAKE_TIMES_USED_Stat(final long contactId,boolean needDeleteCallLog)
+    {
+              /*String sql="select "+Tables.RAW_CONTACTS+"."+RawContacts._ID+" from "+Tables.RAW_CONTACTS+" where "+RawContacts.CONTACT_ID+" =" +contactId;
+              sql="select "+DataColumns.CONCRETE_ID+" from "+Tables.DATA+" where "+Tables.DATA+".["+Data.RAW_CONTACT_ID+"] in ("+sql+")";
+              */
+       ArrayList<Long> idsList=new ArrayList<Long>();
+              Uri uri=RawContacts.CONTENT_URI;
+        Cursor cursor=null;
+        String projects[]=new String[]{RawContacts._ID};
+       String selection=RawContacts.CONTACT_ID+" = "+contactId;
+       String[] selectionArgs=null;
+              try {
+                  cursor=getContext().getContentResolver().query(uri,projects,selection,selectionArgs,null);
+                      if (cursor.getCount() > 0) {
+                              cursor.moveToFirst();
+                              do
+                              {
+                                     idsList.add(cursor.getLong(0));
+                              }while(cursor.moveToNext());
+                      } else {
+                              Log.wtf(TAG, "warning!There is no record for contactId="+contactId);
+                          }
+              } finally {
+                      if(cursor!=null)
+                  cursor.close();
+              }   
+              int res=0;
+              uri=Data.CONTENT_URI;
+        cursor=null;
+        projects=new String[]{Data._ID};
+       selection=RawContacts.CONTACT_ID+" = "+contactId;
+       selectionArgs=null;
+              try {
+                  cursor=getContext().getContentResolver().query(uri,projects,selection,selectionArgs,null);
+                      if (cursor.getCount() > 0) {
+                              cursor.moveToFirst();
+                              do
+                              {
+                                     idsList.add(cursor.getLong(0));
+                              }while(cursor.moveToNext());
+                      } else {
+                              Log.wtf(TAG, "warning!There is no record for contactId="+contactId);
+                          }
+              } finally {
+                      if(cursor!=null)
+                  cursor.close();
+              } 
+              long dataIds[]=new long[idsList.size()];
+              for(int i=0;i<dataIds.length;i++)
+                      dataIds[i]=idsList.get(i);
+              res=update_FAKE_TIMES_USED_Stat(dataIds);
+              if(needDeleteCallLog)
+                      deleteCallLog(idsList,ID_TYPE_RAW_CONTACT);
+              return res;
+    }
+    final int deleteCallLog(ArrayList<Long> dataIdsList)
+    {
+       return deleteCallLog(dataIdsList,ID_TYPE_VIEW_DATA);
+    }
+    int deleteCallLog(ArrayList<Long> idsList,int idType)
+    {
+       int count=0;
+        if(idsList.size()>0)
+        {
+              StringBuffer strBuffer=new StringBuffer();
+              for(Long id:idsList)
+              {
+                      strBuffer.append(id);
+                      strBuffer.append(",");
+              }
+              if(strBuffer.length()>0)
+                      strBuffer.deleteCharAt(strBuffer.length()-1);
+              String selection=null;
+              String[] selectionArgs=null;
+              if(idType==ID_TYPE_VIEW_DATA)
+              {
+                      selection=Calls.DATA_ID+" in ("+strBuffer.toString()+")";
+              }
+              else if (idType==ID_TYPE_RAW_CONTACT)
+              {
+                      selection=Calls.RAW_CONTACT_ID+" in ("+strBuffer.toString()+")";
+              }
+              else
+              {
+                      return 0;
+              }
+              Uri uri=Uri.parse("content://"+CallLog.AUTHORITY+"/calls?updateFakeTimesUsed=false");
+              count=getContext().getContentResolver().delete(uri, selection,selectionArgs );
+        }
+        return count;
+    }
添加移除常用联系功能,需要修改的另外一个应用程序是com.android.contacts。
在MTK6575平台上,需要修改的文件有:

      modified: packages/apps/Contacts/src/com/android/contacts/activities/DialtactsActivity.java
      modified: packages/apps/Contacts/src/com/android/contacts/activities/PeopleActivity.java
      modified: packages/apps/Contacts/src/com/android/contacts/group/GroupDetailFragment.java
      modified: packages/apps/Contacts/src/com/android/contacts/list/ContactTileAdapter.java
      modified: packages/apps/Contacts/src/com/android/contacts/list/ContactTileListFragment.java
      modified: packages/apps/Contacts/src/com/android/contacts/list/ContactTileView.java
      modified: packages/apps/Contacts/src/com/android/contacts/list/PhoneFavoriteFragment.java
      modified: packages/apps/Contacts/res/values-zh-rCN/strings.xml
      modified: packages/apps/Contacts/res/values-zh-rTW/strings.xml
      modified: packages/apps/Contacts/res/values/strings.xml

文件packages/apps/Contacts/src/com/android/contacts/activities/DialtactsActivity.java的主要修改如下:

@@ -935,17 +939,95 @@ public class DialtactsActivity extends TransactionSafeActivity implements Provid
             enterSearchUi();
         }
     };
-
+    /*robin_20120509*/
     private PhoneFavoriteFragment.Listener mPhoneFavoriteListener =
             new PhoneFavoriteFragment.Listener() {
         @Override
-        public void onContactSelected(Uri contactUri) {
+        public void onContactClick(Uri contactUri) {
             PhoneNumberInteraction.startInteractionForPhoneCall(
                     DialtactsActivity.this, contactUri,
                     CALL_ORIGIN_DIALTACTS);
         }
+        @Override
+        public boolean onContactLongClick(Uri contactUri,int type) {
+              if (type==ViewTypes.FREQUENT)
+              {
+                      final Uri contactLookUpUri=contactUri;
+                              Runnable r=new Runnable(){
+
+                                     @Override
+                                     public void run() {
+                                             removeFrequentContact(contactLookUpUri);
+                                     }};
+                      showRemoveFrequentContactAlertDialog(r);
+                      return true;
+              }
+            return false;
+        }
     };
+    Handler handler=new Handler();
+    IContentProvider mContentProvider;
+    final static String ContactsProvider_CALL_METHOD_UPDATE_FAKE_TIMES_USED="CALL_METHOD_update_FAKE_TIMES_USED_Stat";
+    void removeFrequentContact(Uri contactUri)
+    {
+              IContentProvider cp = null;
+        synchronized (this) {
+            cp = mContentProvider;
+            if (cp == null) {
+                cp = mContentProvider =getContentResolver().acquireProvider(ContactsContract.AUTHORITY);
+            }
+        }
+        try {
+              Bundle bundle=new Bundle();
+              bundle.putString("Uri", contactUri.toString());
+            Bundle b = cp.call(ContactsProvider_CALL_METHOD_UPDATE_FAKE_TIMES_USED, "", bundle);
+            if (b != null) {
+                int v = b.getInt("count",0);
+                if(v>0)
+                {
+                      Toast.makeText(this, R.string.remove_frequent_contact_succes, Toast.LENGTH_SHORT).show();
+                      return;
+                }
+            }
+            Toast.makeText(this, R.string.remove_frequent_contact_fail, Toast.LENGTH_SHORT).show();
+            // If the response Bundle is null, we fall through
+            // to the query interface below.
+        } catch (RemoteException e) {
+           Log.w(TAG, "", e);
+            // Not supported by the remote side?  Fall through
+            // to query().
+        }     
+    }
+
+AlertDialog removeFrequentContactAlertDialog;
+void showRemoveFrequentContactAlertDialog(final Runnable runnable)
+{
+               AlertDialog.Builder dialogBuilder=new AlertDialog.Builder(this);
+              dialogBuilder.setMessage(R.string.remove_frequent_contact_alert);
+              dialogBuilder.setCancelable(true);
+              DialogInterface.OnClickListener negativeListener=new DialogInterface.OnClickListener(){
+
+                      @Override
+                      public void onClick(DialogInterface arg0, int arg1) {
+                      
+              }};
+              DialogInterface.OnClickListener positiveListener=new DialogInterface.OnClickListener(){
 
+                      @Override
+                      public void onClick(DialogInterface arg0, int arg1) {
+                              handler.post(runnable);
+                      
+              }
+       };
+       dialogBuilder.setNegativeButton(android.R.string.cancel, negativeListener);
+       dialogBuilder.setPositiveButton(android.R.string.ok, positiveListener);
+       removeFrequentContactAlertDialog=dialogBuilder.create();
+       removeFrequentContactAlertDialog.show();
+}
+/*robin_20120509*/

文件packages/apps/Contacts/src/com/android/contacts/activities/PeopleActivity.java的主要修改如下:

@@ -1340,19 +1345,97 @@ public class PeopleActivity extends ContactsActivity
             startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
         }
     }
-
+    /*[robin_20120509*/
     private final class StrequentContactListFragmentListener
             implements ContactTileListFragment.Listener {
         @Override
-        public void onContactSelected(Uri contactUri, Rect targetRect) {
+        public void onContactClick(Uri contactUri, Rect targetRect) {
             if (PhoneCapabilityTester.isUsingTwoPanes(PeopleActivity.this)) {
                 QuickContact.showQuickContact(PeopleActivity.this, targetRect, contactUri, 0, null);
             } else {
                 startActivity(new Intent(Intent.ACTION_VIEW, contactUri));
             }
         }
+        @Override
+        public boolean onContactLongClick(Uri contactUri, Rect targetRect,int type) {
+              if (type==ViewTypes.FREQUENT)
+              {
+                      final Uri contactLookUpUri=contactUri;
+                              Runnable r=new Runnable(){
+
+                                     @Override
+                                     public void run() {
+                                             // TODO Auto-generated method stub
+                                             removeFrequentContact(contactLookUpUri);
+                                     }};
+                      showRemoveFrequentContactAlertDialog(r);
+                      return true;
+              }
+              return false;
+        }
+    }
+    Handler handler=new Handler();
+    IContentProvider mContentProvider;
+    final static String ContactsProvider_CALL_METHOD_UPDATE_FAKE_TIMES_USED="CALL_METHOD_update_FAKE_TIMES_USED_Stat";
+    void removeFrequentContact(Uri contactUri)
+    {
+              IContentProvider cp = null;
+        synchronized (this) {
+            cp = mContentProvider;
+            if (cp == null) {
+                cp = mContentProvider =getContentResolver().acquireProvider(ContactsContract.AUTHORITY);
+            }
+        }
+        try {
+              Bundle bundle=new Bundle();
+              bundle.putString("Uri", contactUri.toString());
+            Bundle b = cp.call(ContactsProvider_CALL_METHOD_UPDATE_FAKE_TIMES_USED, "ID_TYPE_CONTACT", bundle);
+            if (b != null) {
+                int v = b.getInt("count",0);
+                if(v>0)
+                {
+                      Toast.makeText(this, R.string.remove_frequent_contact_succes, Toast.LENGTH_SHORT).show();
+                      return;
+                }
+            }
+            Toast.makeText(this, R.string.remove_frequent_contact_fail, Toast.LENGTH_SHORT).show();
+            /* If the response Bundle is null, we fall through
+            to the query interface below.*/
+        } catch (RemoteException e) {
+           Log.w(TAG, "", e);
+            /** Not supported by the remote side?  Fall through
+             to query().*/
+        }     
     }
 
+AlertDialog removeFrequentContactAlertDialog;
+void showRemoveFrequentContactAlertDialog(final Runnable runnable)
+{
+              AlertDialog.Builder dialogBuilder=new AlertDialog.Builder(this);
+              dialogBuilder.setMessage(R.string.remove_frequent_contact_alert);
+              dialogBuilder.setCancelable(true);
+              DialogInterface.OnClickListener negativeListener=new DialogInterface.OnClickListener(){
+
+                      @Override
+                      public void onClick(DialogInterface arg0, int arg1) {
+                              /* TODO Auto-generated method stub*/
+                      
+              }};
+              DialogInterface.OnClickListener positiveListener=new DialogInterface.OnClickListener(){
+
+                      @Override
+                      public void onClick(DialogInterface arg0, int arg1) {
+                              /* TODO Auto-generated method stub*/
+                              handler.post(runnable);
+                      
+              }
+       };
+       dialogBuilder.setNegativeButton(android.R.string.cancel, negativeListener);
+       dialogBuilder.setPositiveButton(android.R.string.ok, positiveListener);
+       removeFrequentContactAlertDialog=dialogBuilder.create();
+       removeFrequentContactAlertDialog.show();
+}
+/*robin_20120509]*/
     private final class GroupBrowserActionListener implements OnGroupBrowserActionListener {

packages/apps/Contacts/src/com/android/contacts/calllog/CallLogAdapter.java文件修改如下

@@ -398,7 +398,18 @@ implements CallLogGroupBuilder.GroupCreator, OnScrollListener{
             if (OperatorUtils.getOptrProperties().equals("OP02")) {
                 contactInfo.photoId = (slotId == 0) ? -3 : -4;
             } else {
-                contactInfo.photoId = SimCardUtils.isSimUsimType(slotId) ? -2 : -1;
+               // contactInfo.photoId = SimCardUtils.isSimUsimType(slotId) ? -2 : -1;
+                              if(SimCardUtils.isSimUsimType(slotId)){
+                                     if(slotId == 0)
+                                             contactInfo.photoId = -5;
+                                     else
+                                             contactInfo.photoId = -6;
+                              }else{
+                                     if(slotId == 0)
+                                             contactInfo.photoId = -7;
+                                     else
+                                             contactInfo.photoId = -8;
+                              }
             }
         }

 文件packages/apps/Contacts/src/com/android/contacts/list/ContactTileAdapter.java的主要修改如下:

@@ -276,12 +277,20 @@ public class ContactTileAdapter extends BaseAdapter {
         } else {
                 boolean isUsim = SimCardUtils.isSimUsimType(slotId);
                 if (isUsim) {
-                    Log.i(TAG, "-----------usim");
-                    contact.photoUri = Uri.parse("content://usim");
+                                     //Log.i(TAG, "-----------usim");
+                                     //contact.photoUri = Uri.parse("content://usim");
+                    if(slotId == 0)
+                      contact.photoUri = Uri.parse("content://usim1");
+                                     else
+                                             contact.photoUri = Uri.parse("content://usim2");
                 } else {
-                    Log.i(TAG, "-----------sim");
-                    contact.photoUri = Uri.parse("content://sim");
-                }
+                               //Log.i(TAG, "-----------sim");
+                     //contact.photoUri = Uri.parse("content://sim");
+                      if(slotId == 0)
+                           contact.photoUri = Uri.parse("content://sim1");
+                                      else
+                                             contact.photoUri = Uri.parse("content://sim2");
+                              }
         }
         /*
          * New feature by Mediatek End
@@ -524,10 +533,28 @@ public class ContactTileAdapter extends BaseAdapter {
         @Override
         public void onClick(ContactTileView contactTileView) {
             if (mListener != null) {
-                mListener.onContactSelected(contactTileView.getLookupUri(),
+                mListener.onContactClick(contactTileView.getLookupUri(),
                         ContactsUtils.getTargetRectFromView(mContext, contactTileView));
             }
         }
+        /*robin_20120509*/
+        @Override
+        public boolean onLongClick(ContactTileView contactTileView) {
+              ContactTileRow v=null;
+              int type=-1;
+              ViewParent p=contactTileView.getParent();
+              if(p instanceof ContactTileRow)
+              {
+                      v=(ContactTileRow)p;
+                      type=v.getItemViewType();
+                   if (type==ViewTypes.FREQUENT&&mListener != null) {
+                       return mListener.onContactLongClick(contactTileView.getLookupUri(),
+                               ContactsUtils.getTargetRectFromView(mContext, contactTileView),type);
+                   }
+              }
+            return false;
+        }
+      //robin_20120509]
     };
 
     /**
@@ -544,7 +571,10 @@ public class ContactTileAdapter extends BaseAdapter {
             mItemViewType = itemViewType;
             mLayoutResId = getLayoutResourceId(mItemViewType);
         }
-
+        int getItemViewType()
+        {
+              return  mItemViewType;
+        }
         /**
          * Configures the row to add {@link ContactEntry}s information to the views
          */
@@ -707,7 +737,7 @@ public class ContactTileAdapter extends BaseAdapter {
         public int indexSimOrPhone;
     }
 
-    private static class ViewTypes {
+    public static class ViewTypes {
         public static final int COUNT = 4;
         public static final int STARRED = 0;
         public static final int DIVIDER = 1;
@@ -716,7 +746,8 @@ public class ContactTileAdapter extends BaseAdapter {
     }
 
     public interface Listener {
-        public void onContactSelected(Uri contactUri, Rect targetRect);
+        public void onContactClick(Uri contactUri, Rect targetRect);
+        public boolean onContactLongClick(Uri contactUri, Rect targetRect,int type);
     }

文件apps/Contacts/src/com/android/contacts/list/ContactTileListFragment.java主要修改如下:

@@ -56,7 +56,8 @@ public class ContactTileListFragment extends Fragment {
     private static final String TAG = ContactTileListFragment.class.getSimpleName();
 
     public interface Listener {
-        public void onContactSelected(Uri contactUri, Rect targetRect);
+        public void onContactClick(Uri contactUri, Rect targetRect);
+        public boolean onContactLongClick(Uri contactUri, Rect targetRect,int type);
     }
 
     private static int LOADER_CONTACTS = 1;
@@ -221,11 +222,18 @@ public class ContactTileListFragment extends Fragment {
     private ContactTileAdapter.Listener mAdapterListener =
             new ContactTileAdapter.Listener() {
         @Override
-        public void onContactSelected(Uri contactUri, Rect targetRect) {
+        public void onContactClick(Uri contactUri, Rect targetRect) {
             if (mListener != null) {
-                mListener.onContactSelected(contactUri, targetRect);
+                mListener.onContactClick(contactUri, targetRect);
             }
         }
+        @Override
+        public boolean onContactLongClick(Uri contactUri, Rect targetRect,int type) {
+            if (mListener != null) {
+                return mListener.onContactLongClick(contactUri, targetRect,type);
+            }
+            return false;
+        }
     };

文件packages/apps/Contacts/src/com/android/contacts/list/ContactTileView.java修改如下:

@@ -72,11 +72,21 @@ public class ContactTileView extends FrameLayout {
                 }
             }
         };
-
+        OnLongClickListener listener2 = new OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                 if (mListener != null) {
+                    return mListener.onLongClick(ContactTileView.this);
+                }
+                return false;
+            }
+        };
         if(mPushState != null) {
             mPushState.setOnClickListener(listener);
+            mPushState.setOnLongClickListener(listener2);
         } else {
             setOnClickListener(listener);
+            setOnLongClickListener(listener2);
         }
     }
 
@@ -166,5 +176,6 @@ public class ContactTileView extends FrameLayout {
 
     public interface Listener {
         void onClick(ContactTileView contactTileView);
+        boolean onLongClick(ContactTileView contactTileView);
     }
 }

文件packages/apps/Contacts/src/com/android/contacts/list/PhoneFavoriteFragment.java的主要修改如下:

@@ -74,7 +74,8 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
     private static final int REQUEST_CODE_ACCOUNT_FILTER = 1;
 
     public interface Listener {
-        public void onContactSelected(Uri contactUri);
+        public void onContactClick(Uri contactUri);
+        public boolean onContactLongClick(Uri contactUri,int type);
     }
 
     private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
@@ -189,11 +190,18 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
 
     private class ContactTileAdapterListener implements ContactTileAdapter.Listener {
         @Override
-        public void onContactSelected(Uri contactUri, Rect targetRect) {
+        public void onContactClick(Uri contactUri, Rect targetRect) {
             if (mListener != null) {
-                mListener.onContactSelected(contactUri);
+                mListener.onContactClick(contactUri);
             }
         }
+        @Override
+        public boolean onContactLongClick(Uri contactUri, Rect targetRect,int type) {
+            if (mListener != null) {
+                return mListener.onContactLongClick(contactUri,type);
+            }
+            return false;
+        }
     }
 
     private class FilterHeaderClickListener implements OnClickListener {
@@ -426,7 +434,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
         } else {
             final int localPosition = position - mContactTileAdapter.getCount() - 1;
             if (mListener != null) {
-                mListener.onContactSelected(mAllContactsAdapter.getDataUri(localPosition));
+                mListener.onContactClick(mAllContactsAdapter.getDataUri(localPosition));
             }
         }
     }

文件packages/apps/Contacts/src/com/android/contacts/group/GroupDetailFragment.java修改如下:

@@ -256,9 +256,13 @@ public class GroupDetailFragment extends Fragment implements OnScrollListener {
             new ContactTileAdapter.Listener() {
 
         @Override
-        public void onContactSelected(Uri contactUri, Rect targetRect) {
+        public void onContactClick(Uri contactUri, Rect targetRect) {
             mListener.onContactSelected(contactUri);
         }
+        @Override
+        public boolean onContactLongClick(Uri contactUri, Rect targetRect,int type) {
+            return false;
+        }
     };

 
文件packages/apps/Contacts/res/values/strings.xml修改如下:

@@ -2139,4 +2139,7 @@
     <string name="error_save_usim_contact_email_lost">"Failed to save Email address because the USIM storage for Email is full."</string>
     <string name="error_import_usim_contact_email_lost">"Failure caused by USIM storage full for Email.\nCompleted: <xliff:g id="items">%d</xliff:g>\nIncomp
     <string name="user_profile_cannot_sd_card">Cannot share the content with this method.</string>
+       <string name="remove_frequent_contact_alert">Do you want to remove this contact from frequent?</string>
+       <string name="remove_frequent_contact_succes">succes to remove contact from frequent list!</string>
+       <string name="remove_frequent_contact_fail">fail to remove contact from frequent list!</string>
 </resources>

文件packages/apps/Contacts/res/values-zh-rCN/strings.xml修改如下:

@@ -868,4 +868,7 @@
     <string name="user_profile_cannot_sd_card">"无法通过该方式共享个人信息."</string>
     <!-- The previous lines are provided and maintained by Mediatek Inc. -->
     <string name="activity_not_found_error">找不到相关的应用程序!</string>
+    <string name="remove_frequent_contact_alert">你想把该联系人从常用联系人列表中移除吗?</string>
+    <string name="remove_frequent_contact_succes">移除常用联系人成功!</string>
+       <string name="remove_frequent_contact_fail">抱歉,移除常用聯繫人失敗!</string>
 </resources>

文件packages/apps/Contacts/res/values-zh-rTW/strings.xml修改如下:
@@ -888,4 +888,7 @@
     <string name="user_profile_cannot_sd_card">"無法通過該方式共享個人信息"</string>
     <!-- The previous lines are provided and maintained by Mediatek Inc. -->
 <string name="activity_not_found_error">找不到相關的應用程式!</string>
+    <string name="remove_frequent_contact_alert">你想把該聯繫人從常用聯繫人列表中移除嗎?</string>
+        <string name="remove_frequent_contact_succes">移除常用聯繫人成功!</string>
+       <string name="remove_frequent_contact_fail">抱歉,从常用联系人列表中移除联系人失败!</string>

原创粉丝点击