在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 . javapackages / providers / ContactsProvider / src / com / android / providers / contacts / ContactsProvider2 . javapackages / 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
>
\n
Incomp
<
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
>