`
wyk86485480
  • 浏览: 29167 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
文章分类
社区版块
存档分类
最新评论

重新设计实现CSipSimple呼叫记录分组功能

阅读更多

CSipSimple 原有的分组功能只能针对连续相同被叫号码,如果中间有间隔,相同的号码就不会被分成一组。这个实现很弱,也失去了分组的意义。下面针对这块功能的设计实现做下简单记录。

#### 1. 自己封装一个CursorLoader

这里取名为CalllogCursorLoader,在CallLogListFragment -> OnCreateLoader中:

~~~.java
    // Loader
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CalllogCursorLoader(getActivity());
    }
~~~

#### 2. CalllogCursorLoader.java 代码:

~~~.java
package org.phoneos.db;

import org.phoneos.api.SipManager;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.CallLog;
import android.support.v4.content.AsyncTaskLoader;

public class CalllogCursorLoader extends AsyncTaskLoader<Cursor> {
final ForceLoadContentObserver mObserver;
private FastCursor fastCursor = null;
private Cursor mObserverCursor = null;

/**
* Creates an empty unspecified CursorLoader. You must follow this with
* calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc to
* specify the query to perform.
*/
public CalllogCursorLoader(Context context) {
super(context);
mObserver = new ForceLoadContentObserver();
}

/* Runs on a worker thread */
@Override
public Cursor loadInBackground() {

String[] fields = new String[] { CallLog.Calls._ID,
CallLog.Calls.CACHED_NAME, CallLog.Calls.CACHED_NUMBER_LABEL,
CallLog.Calls.CACHED_NUMBER_TYPE, CallLog.Calls.DURATION,
CallLog.Calls.DATE, CallLog.Calls.NEW, CallLog.Calls.NUMBER,
CallLog.Calls.TYPE, SipManager.CALLLOG_PROFILE_ID_FIELD };

try {
if (mObserverCursor != null) {
mObserverCursor.close();
mObserverCursor = null;
}

// get last inserted, a trick for observer data
mObserverCursor = getContext().getContentResolver().query(
SipManager.CALLLOG_URI, fields, null, null,
"date desc limit 1");

if (mObserverCursor != null) {
mObserverCursor.registerContentObserver(mObserver);
}

// if (fastCursor == null) {
Cursor cursor = getContext().getContentResolver().query(
SipManager.CALLLOG_URI, fields, null, null, "date asc");

fastCursor = new FastCursor(cursor);

cursor.close();
cursor = null;

// } else {
// fastCursor.addCursor(mObserverCursor);
// }

// int min = fastCursor.getCount();
// if (min > 100)
// min = 100;
// for (int i = 0; i < min; i++) {
// fastCursor.moveToPosition(i);
// Log.d("LOADER", i + ", " + fastCursor.getString(fastCursor.getColumnIndex(CallLog.Calls.NUMBER)));
// }

return fastCursor;
} finally {
}
}

/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
if (isReset()) {
if (fastCursor != null) {
fastCursor.close();
}
}

Cursor oldCursor = fastCursor;
fastCursor = (FastCursor)cursor;

if (isStarted()) {
super.deliverResult(cursor);
}

if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
oldCursor.close();
}
}

/**
* Starts an asynchronous load of the contacts list data. When the result is
* ready the callbacks will be called on the UI thread. If a previous load
* has been completed and is still valid the result may be passed to the
* callbacks immediately.
*
* Must be called from the UI thread
*/
@Override
protected void onStartLoading() {
if (fastCursor != null) {
deliverResult(fastCursor);
}

if (takeContentChanged() || fastCursor == null) {
forceLoad();
}
}

/**
* Must be called from the UI thread
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}

@Override
public void onCanceled(Cursor data) {
if (fastCursor != null && !fastCursor.isClosed()) {
fastCursor.close();
}
}

@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();

if (fastCursor != null && !fastCursor.isClosed()) {
fastCursor.close();
}

fastCursor = null;
}

}
~~~

#### 3. FastCursor.java 代码:

~~~.java
package org.phoneos.db;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import android.database.AbstractCursor;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.provider.CallLog;
import android.util.Log;

// Custom a cursor, better group call logs, better performace
public class FastCursor extends AbstractCursor {
private HashMap<String, ArrayList<Integer>> groupHashMap = new HashMap<String, ArrayList<Integer>>();
private ArrayList<ArrayList<Integer>> groupList;
private MatrixCursor mCursor;

public FastCursor(Cursor cursor) {
mCursor = new MatrixCursor(cursor.getColumnNames());

int capacity = cursor.getCount() >> 3;
if (capacity < 10)
capacity = 10;
groupList = new ArrayList<ArrayList<Integer>>(capacity);

addCursor(cursor);
}

// Cursor order by date asc
public void addCursor(Cursor cursor) {

for (int index = 0; index < cursor.getCount(); index++) {
cursor.moveToPosition(index);

Object[] columnValues = new Object[cursor.getColumnCount()];
columnValues[0] = cursor.getInt(0);
columnValues[1] = cursor.getString(1);
columnValues[2] = cursor.getString(2);
columnValues[3] = cursor.getInt(3);
columnValues[4] = cursor.getInt(4);
columnValues[5] = cursor.getLong(5);
columnValues[6] = cursor.getInt(6);
columnValues[7] = cursor.getString(7);
columnValues[8] = cursor.getInt(8);
columnValues[9] = cursor.getInt(9);

mCursor.addRow(columnValues);

String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
ArrayList<Integer> list = groupHashMap.get(number);
if (list == null) {
list = new ArrayList<Integer>(4);
groupHashMap.put(number, list);
}
else {
groupList.remove(list);
}

list.add(mCursor.getCount() - 1);
groupList.add(list);
}

// MUST reset mPos, workaroud for AbstractCursor.moveToPosition issue
mPos = -1;

Log.d("LOADER", groupHashMap.toString());
Log.d("LOADER", groupList.toString());
}

@Override
public boolean onMove(int oldPosition, int newPosition) {
int cursorStartPos = 0;
int length = groupList.size();
ArrayList<Integer> list = null;
for (int i = length - 1; i >= 0; i--) {
if (newPosition < (cursorStartPos + groupList.get(i).size())) {
list = groupList.get(i);
break;
}

cursorStartPos += groupList.get(i).size();
}

/* Move it to the right position */
if (list != null) {
int index = list.size() - (newPosition - cursorStartPos) - 1;
Boolean ret = mCursor.moveToPosition(list.get(index));
return ret;
}
return false;
}

// AbstractCursor implementation.

@Override
public void close() {
super.close();

mCursor.close();
groupHashMap.clear();
groupList.clear();

mCursor = null;
groupHashMap = null;
groupList = null;
}

@Override
public int getCount() {
return mCursor.getCount();
}

@Override
public String[] getColumnNames() {
return mCursor.getColumnNames();
}

@Override
public String getString(int column) {
return mCursor.getString(column);
}

@Override
public short getShort(int column) {
return mCursor.getShort(column);
}

@Override
public int getInt(int column) {
return mCursor.getInt(column);
}

@Override
public long getLong(int column) {
return mCursor.getLong(column);
}

@Override
public float getFloat(int column) {
return mCursor.getFloat(column);
}

@Override
public double getDouble(int column) {
return mCursor.getDouble(column);
}

@Override
public byte[] getBlob(int column) {
return mCursor.getBlob(column);
}

@Override
public int getType(int column) {
return mCursor.getType(column);
}

@Override
public boolean isNull(int column) {
return mCursor.isNull(column);
}

}
~~~

#### 4. 修改CallLogGroupBuilder.java

~~~.diff
+++ b/src/org/phoneos/ui/calllog/CallLogGroupBuilder.java
@@ -81,16 +81,17 @@ public class CallLogGroupBuilder {
             final boolean sameNumber = equalNumbers(firstNumber, currentNumber);
             final boolean shouldGroup;

-            if (!sameNumber) {
-                // Should only group with calls from the same number.
-                shouldGroup = false;
-            } else if ( firstCallType == Calls.MISSED_TYPE) {
-                // Voicemail and missed calls should only be grouped with subsequent missed calls.
-                shouldGroup = callType == Calls.MISSED_TYPE;
-            } else {
-                // Incoming and outgoing calls group together.
-                shouldGroup = callType == Calls.INCOMING_TYPE || callType == Calls.OUTGOING_TYPE;
-            }
+            shouldGroup = sameNumber;
~~~

转自:http://www.yinqisen.cn/blog-510.html
分享到:
评论

相关推荐

    CSipSimple

    CSipSimple是一款开源的Android应用,专为移动设备设计,实现了VoIP(Voice over Internet Protocol)功能,即通过互联网进行语音通信。它基于SIP(Session Initiation Protocol)协议,这是一种用于控制多媒体通信...

    CSipSimple可编译版本

    这意味着,除了SIP协议和VoIP应用开发的基本概念外,我们还可以期待学习到关于CSipSimple的特定功能和架构,例如用户界面设计、会话管理、注册流程、安全性和隐私保护等。 由于没有提供具体的压缩包子文件的文件...

    CSipSimple android项目(基于官方demo)

    5. **呼叫历史记录**:查看过去的通话记录,以便回拨或查看通话详情。 **优化与扩展** 1. **性能优化**:为了提供流畅的用户体验,需要对音频和视频编码进行优化,减少延迟和丢包。 2. **安全性**:确保通信过程中...

    CsipSimple源代码

    CsipSimple是一款基于Android平台的开源通信应用,其核心是利用了PJSIP库来实现SIP(Session Initiation Protocol)协议的功能。SIP是一种互联网信令协议,用于建立、管理和终止多媒体通信会话,如语音通话、视频...

    csipsimple

    csipsimple 是开方式比较好用的ip电话软件。兼容标准ip协议。速度快。

    支持视频通话的csipsimple android网络电话

    支持视频通话的csipsimple android网络电话

    csipsimple-master

    6. **UI设计**:为了提供良好的用户体验,csipsimple的界面设计至关重要。这涉及到Android的布局管理、触摸事件处理以及自定义视图等。 7. **安全性**:在VoIP应用中,数据安全和隐私保护是关键。开发者应了解如何...

    Csipsimple二次封装的Demo,AndroidStudio直接运行

    Csipsimple是一款开源的SIP(Session Initiation Protocol)客户端,用于实现VoIP(Voice over IP)功能,支持语音通话、视频通话以及即时消息等通信方式。 在这款Demo中,开发人员已经对原版的Csipsimple进行了...

    csipsimple_(2459)最新版_0积分下载

    CSIPSimple是一款针对Android平台的开源VoIP(Voice over IP)软件,它的主要功能是提供一个用户友好的界面,让用户可以使用互联网进行语音通话、视频通话以及即时消息交流。这款应用基于SIP(Session Initiation ...

    CSipSimple源码

    CSipSimple是一款开源的SIP(Session Initiation Protocol)客户端,专为Android平台设计,用于实现VoIP(Voice over IP)通信。SIP是一种互联网协议,用于建立、修改和终止多媒体通信会话,如语音通话、视频会议等...

    csipsimple 好用的安卓软电话

    csipsimple 好用的安卓软电话,和电话簿完美结合,支持流量监控,支持G729编码,跟bria有一拼

    CSipSimple安装文档

    CSipSimple是一款基于Android操作系统的SIP软电话应用,它允许用户使用VoIP(Voice over Internet Protocol)服务进行语音通话。安装文档提供了在CentOS6.5 32位系统上安装CSipSimple所需步骤的详细说明。文档指出了...

    CSipSimple源码12月15日更新版

    从CSipSimple官网svn上下载的源码。需要用lz工具解压。

    CSipSimple-2.2.apk

    定位功能,轻松定位,能很详细的展示对方所在街道名称和地段。

    CSIPSimple VideoPlugin

    为了提供良好的用户体验,VideoPlugin通常会集成到CSipSimple的UI中,包括视频预览、呼叫控制按钮、视频切换等功能。 9. **兼容性**: 视频插件应考虑与不同Android版本和设备的兼容性,以确保广泛的应用范围。 ...

    CSipsimple-latest-trunk.apk

    android 上sip 软件件,是一个开源的软件,这是人个2012年10年4月更新的一个软件

    CSipSimple支持视频通信版本源码

    最近在研究视频通信,决定使用CSipSimple做二次开发,网上的资源版本都是只支持语音的,自己捣鼓了一下弄出来一个支持视频通信的。 文件解压之后将两个工程直接导入eclipse就可以使用了。使用视频通信需要在设置里面...

    CSipSimple,源码

    取自 https://code.google.com/archive/p/csipsimple/ ,最近项目中遇到,找此源码着实费了一番功夫,特提供出来,方便大家来使用。

Global site tag (gtag.js) - Google Analytics