在上两篇文章中,我们依次介绍openfire部署以及smack常用API的使用,这一节中我们着力介绍如何基于asmack开发一个Android的客户端,本篇的重点在实践,讲解和原理环节,大家可以参考前两篇的文章
基于xmpp openfire smack开发之openfire介绍和部署[1]
基于xmpp openfire smack开发之smack类库介绍和使用[2]
1.源码结构介绍

activity包下存放一些android页面交互相关的控制程序,还有一个些公共帮助类
db包为sqlite的工具类封装,这里做了一些自定义的改造,稍微仿Spring的JdbcTemplate结构,使用起来更加方便一点
manager包留下主要是一些管理组件,包括联系人管理,消息管理,提醒管理,离线消息管理,用户管理,xmpp连接管理
model包中都是一些对象模型,传输介质
service中存放一些android后台的核心服务,主要包括聊天服务,联系人服务,系统消息服务,重连接服务
task包中存放一些耗时的异步操作
util中存放一些常用的工具类
view中一些和android的UI相关的显示控件

anim中存放一些动画元素的配置
layout是布局页面
menu是地步菜单布局页面
values中存放一些字符,颜色,样式,参数的配置信息
其中strings.xml中,保存的缺省配置为gtalk的服务器信息,大家如果有谷歌gtalk的账号可以直接登录,否则需要更改这里的配置才可以使用其他的xmpp服务器
-
-
<integer name="xmpp_port">5222</integer>
-
<string name="xmpp_host">talk.google.com</string>
-
<string name="xmpp_service_name">gmail.com</string>
-
<bool name="is_remember">true</bool>
-
<bool name="is_autologin">false</bool>
-
<bool name="is_novisible">false</bool>
AndroidManifest.xml为android功能清单的配置文件,我们这里开放的权限并不多
-
-
<uses-permission android:name="android.permission.INTERNET" />
-
-
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-
-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-
<span style="WHITE-SPACE: pre"> </span>
-
<span style="WHITE-SPACE: pre"> </span><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
-
<span style="WHITE-SPACE: pre"> </span>
-
<span style="WHITE-SPACE: pre"> </span><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2.核心类介绍
1.ActivitySupport类
-
package csdn.shimiso.eim.activity;
-
-
import android.app.Activity;
-
import android.app.AlertDialog;
-
import android.app.Notification;
-
import android.app.NotificationManager;
-
import android.app.PendingIntent;
-
import android.app.ProgressDialog;
-
import android.content.Context;
-
import android.content.DialogInterface;
-
import android.content.Intent;
-
import android.content.SharedPreferences;
-
import android.location.LocationManager;
-
import android.net.ConnectivityManager;
-
import android.net.NetworkInfo;
-
import android.os.Bundle;
-
import android.os.Environment;
-
import android.provider.Settings;
-
import android.view.inputmethod.InputMethodManager;
-
import android.widget.Toast;
-
import csdn.shimiso.eim.R;
-
import csdn.shimiso.eim.comm.Constant;
-
import csdn.shimiso.eim.model.LoginConfig;
-
import csdn.shimiso.eim.service.IMChatService;
-
import csdn.shimiso.eim.service.IMContactService;
-
import csdn.shimiso.eim.service.IMSystemMsgService;
-
import csdn.shimiso.eim.service.ReConnectService;
-
-
-
-
-
-
-
-
public class ActivitySupport extends Activity implements IActivitySupport {
-
-
protected Context context = null;
-
protected SharedPreferences preferences;
-
protected EimApplication eimApplication;
-
protected ProgressDialog pg = null;
-
protected NotificationManager notificationManager;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
context = this;
-
preferences = getSharedPreferences(Constant.LOGIN_SET, 0);
-
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-
pg = new ProgressDialog(context);
-
eimApplication = (EimApplication) getApplication();
-
eimApplication.addActivity(this);
-
}
-
-
@Override
-
protected void onStart() {
-
super.onStart();
-
}
-
-
@Override
-
protected void onResume() {
-
super.onResume();
-
}
-
-
@Override
-
protected void onPause() {
-
super.onPause();
-
}
-
-
@Override
-
protected void onStop() {
-
super.onStop();
-
}
-
-
@Override
-
public void onDestroy() {
-
super.onDestroy();
-
}
-
-
@Override
-
public ProgressDialog getProgressDialog() {
-
return pg;
-
}
-
-
@Override
-
public void startService() {
-
-
Intent server = new Intent(context, IMContactService.class);
-
context.startService(server);
-
-
Intent chatServer = new Intent(context, IMChatService.class);
-
context.startService(chatServer);
-
-
Intent reConnectService = new Intent(context, ReConnectService.class);
-
context.startService(reConnectService);
-
-
Intent imSystemMsgService = new Intent(context,
-
IMSystemMsgService.class);
-
context.startService(imSystemMsgService);
-
}
-
-
-
-
-
-
-
-
-
@Override
-
public void stopService() {
-
-
Intent server = new Intent(context, IMContactService.class);
-
context.stopService(server);
-
-
Intent chatServer = new Intent(context, IMChatService.class);
-
context.stopService(chatServer);
-
-
-
Intent reConnectService = new Intent(context, ReConnectService.class);
-
context.stopService(reConnectService);
-
-
-
Intent imSystemMsgService = new Intent(context,
-
IMSystemMsgService.class);
-
context.stopService(imSystemMsgService);
-
}
-
-
@Override
-
public void isExit() {
-
new AlertDialog.Builder(context).setTitle("确定退出吗?")
-
.setNeutralButton("确定", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
stopService();
-
eimApplication.exit();
-
}
-
})
-
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
dialog.cancel();
-
}
-
}).show();
-
}
-
-
@Override
-
public boolean hasInternetConnected() {
-
ConnectivityManager manager = (ConnectivityManager) context
-
.getSystemService(context.CONNECTIVITY_SERVICE);
-
if (manager != null) {
-
NetworkInfo network = manager.getActiveNetworkInfo();
-
if (network != null && network.isConnectedOrConnecting()) {
-
return true;
-
}
-
}
-
return false;
-
}
-
-
@Override
-
public boolean validateInternet() {
-
ConnectivityManager manager = (ConnectivityManager) context
-
.getSystemService(context.CONNECTIVITY_SERVICE);
-
if (manager == null) {
-
openWirelessSet();
-
return false;
-
} else {
-
NetworkInfo[] info = manager.getAllNetworkInfo();
-
if (info != null) {
-
for (int i = 0; i < info.length; i++) {
-
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
-
return true;
-
}
-
}
-
}
-
}
-
openWirelessSet();
-
return false;
-
}
-
-
@Override
-
public boolean hasLocationGPS() {
-
LocationManager manager = (LocationManager) context
-
.getSystemService(context.LOCATION_SERVICE);
-
if (manager
-
.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) {
-
return true;
-
} else {
-
return false;
-
}
-
}
-
-
@Override
-
public boolean hasLocationNetWork() {
-
LocationManager manager = (LocationManager) context
-
.getSystemService(context.LOCATION_SERVICE);
-
if (manager
-
.isProviderEnabled(android.location.LocationManager.NETWORK_PROVIDER)) {
-
return true;
-
} else {
-
return false;
-
}
-
}
-
-
@Override
-
public void checkMemoryCard() {
-
if (!Environment.MEDIA_MOUNTED.equals(Environment
-
.getExternalStorageState())) {
-
new AlertDialog.Builder(context)
-
.setTitle(R.string.prompt)
-
.setMessage("请检查内存卡")
-
.setPositiveButton(R.string.menu_settings,
-
new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog,
-
int which) {
-
dialog.cancel();
-
Intent intent = new Intent(
-
Settings.ACTION_SETTINGS);
-
context.startActivity(intent);
-
}
-
})
-
.setNegativeButton("退出",
-
new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog,
-
int which) {
-
dialog.cancel();
-
eimApplication.exit();
-
}
-
}).create().show();
-
}
-
}
-
-
public void openWirelessSet() {
-
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
-
dialogBuilder
-
.setTitle(R.string.prompt)
-
.setMessage(context.getString(R.string.check_connection))
-
.setPositiveButton(R.string.menu_settings,
-
new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog,
-
int which) {
-
dialog.cancel();
-
Intent intent = new Intent(
-
Settings.ACTION_WIRELESS_SETTINGS);
-
context.startActivity(intent);
-
}
-
})
-
.setNegativeButton(R.string.close,
-
new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog,
-
int whichButton) {
-
dialog.cancel();
-
}
-
});
-
dialogBuilder.show();
-
}
-
-
-
-
-
-
-
-
-
-
-
public void showToast(String text, int longint) {
-
Toast.makeText(context, text, longint).show();
-
}
-
-
@Override
-
public void showToast(String text) {
-
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
-
}
-
-
-
-
-
-
-
-
-
public void closeInput() {
-
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
-
if (inputMethodManager != null && this.getCurrentFocus() != null) {
-
inputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus()
-
.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
-
}
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
public void setNotiType(int iconId, String contentTitle,
-
String contentText, Class activity, String from) {
-
-
-
-
Intent notifyIntent = new Intent(this, activity);
-
notifyIntent.putExtra("to", from);
-
-
-
-
PendingIntent appIntent = PendingIntent.getActivity(this, 0,
-
notifyIntent, 0);
-
-
-
Notification myNoti = new Notification();
-
-
myNoti.flags = Notification.FLAG_AUTO_CANCEL;
-
-
myNoti.icon = iconId;
-
-
myNoti.tickerText = contentTitle;
-
-
myNoti.defaults = Notification.DEFAULT_SOUND;
-
-
myNoti.setLatestEventInfo(this, contentTitle, contentText, appIntent);
-
-
notificationManager.notify(0, myNoti);
-
}
-
-
@Override
-
public Context getContext() {
-
return context;
-
}
-
-
@Override
-
public SharedPreferences getLoginUserSharedPre() {
-
return preferences;
-
}
-
-
@Override
-
public void saveLoginConfig(LoginConfig loginConfig) {
-
preferences.edit()
-
.putString(Constant.XMPP_HOST, loginConfig.getXmppHost())
-
.commit();
-
preferences.edit()
-
.putInt(Constant.XMPP_PORT, loginConfig.getXmppPort()).commit();
-
preferences
-
.edit()
-
.putString(Constant.XMPP_SEIVICE_NAME,
-
loginConfig.getXmppServiceName()).commit();
-
preferences.edit()
-
.putString(Constant.USERNAME, loginConfig.getUsername())
-
.commit();
-
preferences.edit()
-
.putString(Constant.PASSWORD, loginConfig.getPassword())
-
.commit();
-
preferences.edit()
-
.putBoolean(Constant.IS_AUTOLOGIN, loginConfig.isAutoLogin())
-
.commit();
-
preferences.edit()
-
.putBoolean(Constant.IS_NOVISIBLE, loginConfig.isNovisible())
-
.commit();
-
preferences.edit()
-
.putBoolean(Constant.IS_REMEMBER, loginConfig.isRemember())
-
.commit();
-
preferences.edit()
-
.putBoolean(Constant.IS_ONLINE, loginConfig.isOnline())
-
.commit();
-
preferences.edit()
-
.putBoolean(Constant.IS_FIRSTSTART, loginConfig.isFirstStart())
-
.commit();
-
}
-
-
@Override
-
public LoginConfig getLoginConfig() {
-
LoginConfig loginConfig = new LoginConfig();
-
String a = preferences.getString(Constant.XMPP_HOST, null);
-
String b = getResources().getString(R.string.xmpp_host);
-
loginConfig.setXmppHost(preferences.getString(Constant.XMPP_HOST,
-
getResources().getString(R.string.xmpp_host)));
-
loginConfig.setXmppPort(preferences.getInt(Constant.XMPP_PORT,
-
getResources().getInteger(R.integer.xmpp_port)));
-
loginConfig.setUsername(preferences.getString(Constant.USERNAME, null));
-
loginConfig.setPassword(preferences.getString(Constant.PASSWORD, null));
-
loginConfig.setXmppServiceName(preferences.getString(
-
Constant.XMPP_SEIVICE_NAME,
-
getResources().getString(R.string.xmpp_service_name)));
-
loginConfig.setAutoLogin(preferences.getBoolean(Constant.IS_AUTOLOGIN,
-
getResources().getBoolean(R.bool.is_autologin)));
-
loginConfig.setNovisible(preferences.getBoolean(Constant.IS_NOVISIBLE,
-
getResources().getBoolean(R.bool.is_novisible)));
-
loginConfig.setRemember(preferences.getBoolean(Constant.IS_REMEMBER,
-
getResources().getBoolean(R.bool.is_remember)));
-
loginConfig.setFirstStart(preferences.getBoolean(
-
Constant.IS_FIRSTSTART, true));
-
return loginConfig;
-
}
-
-
@Override
-
public boolean getUserOnlineState() {
-
-
return preferences.getBoolean(Constant.IS_ONLINE, true);
-
}
-
-
@Override
-
public void setUserOnlineState(boolean isOnline) {
-
-
preferences.edit().putBoolean(Constant.IS_ONLINE, isOnline).commit();
-
-
}
-
-
@Override
-
public EimApplication getEimApplication() {
-
return eimApplication;
-
}
-
}
大家写android程序会发现,不同的activity之间经常需要调用一些公共的资源,这里的资源不仅包括android自身的,还有我们自己的管理服务类,甚至相互之间传递一些参数,这里我仿照struts2的设计,提炼出一个ActivitySupport类,同时抽取一个接口,让所有的Activity都集成这个类,因为有了接口,我们便可以采用回调模式,非常方便的传递数据和使用公共的资源,这种好处相信大家使用之后都能有深刻的体会,通过接口回调传递参数和相互调用的方式无疑是最优雅的,spring和hibernate源码中曾经大量使用这种结构。
2.SQLiteTemplate类
-
package csdn.shimiso.eim.db;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
import android.content.ContentValues;
-
import android.database.Cursor;
-
import android.database.sqlite.SQLiteDatabase;
-
-
-
-
-
-
-
-
-
public class SQLiteTemplate {
-
-
-
-
protected String mPrimaryKey = "_id";
-
-
-
-
-
private DBManager dBManager;
-
-
-
-
private boolean isTransaction = false;
-
-
-
-
private SQLiteDatabase dataBase = null;
-
-
private SQLiteTemplate() {
-
}
-
-
private SQLiteTemplate(DBManager dBManager, boolean isTransaction) {
-
this.dBManager = dBManager;
-
this.isTransaction = isTransaction;
-
}
-
-
-
-
-
-
-
-
public static SQLiteTemplate getInstance(DBManager dBManager,
-
boolean isTransaction) {
-
return new SQLiteTemplate(dBManager, isTransaction);
-
}
-
-
-
-
-
-
-
-
public void execSQL(String sql) {
-
try {
-
dataBase = dBManager.openDatabase();
-
dataBase.execSQL(sql);
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
}
-
-
-
-
-
-
-
-
public void execSQL(String sql, Object[] bindArgs) {
-
try {
-
dataBase = dBManager.openDatabase();
-
dataBase.execSQL(sql, bindArgs);
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
}
-
-
-
-
-
-
-
-
-
-
public long insert(String table, ContentValues content) {
-
try {
-
dataBase = dBManager.openDatabase();
-
-
return dataBase.insert(table, null, content);
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
return 0;
-
}
-
-
-
-
-
-
-
public void deleteByIds(String table, Object... primaryKeys) {
-
try {
-
if (primaryKeys.length > 0) {
-
StringBuilder sb = new StringBuilder();
-
for (@SuppressWarnings("unused")
-
Object id : primaryKeys) {
-
sb.append("?").append(",");
-
}
-
sb.deleteCharAt(sb.length() - 1);
-
dataBase = dBManager.openDatabase();
-
dataBase.execSQL("delete from " + table + " where "
-
+ mPrimaryKey + " in(" + sb + ")",
-
(Object[]) primaryKeys);
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
}
-
-
-
-
-
-
-
-
-
-
public int deleteByField(String table, String field, String value) {
-
try {
-
dataBase = dBManager.openDatabase();
-
return dataBase.delete(table, field + "=?", new String[] { value });
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
return 0;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
public int deleteByCondition(String table, String whereClause,
-
String[] whereArgs) {
-
try {
-
dataBase = dBManager.openDatabase();
-
return dataBase.delete(table, whereClause, whereArgs);
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
return 0;
-
}
-
-
-
-
-
-
-
-
-
public int deleteById(String table, String id) {
-
try {
-
dataBase = dBManager.openDatabase();
-
return deleteByField(table, mPrimaryKey, id);
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
return 0;
-
}
-
-
-
-
-
-
-
-
-
-
public int updateById(String table, String id, ContentValues values) {
-
try {
-
dataBase = dBManager.openDatabase();
-
return dataBase.update(table, values, mPrimaryKey + "=?",
-
new String[] { id });
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
return 0;
-
}
-
-
-
-
-
-
-
-
-
-
-
public int update(String table, ContentValues values, String whereClause,
-
String[] whereArgs) {
-
try {
-
dataBase = dBManager.openDatabase();
-
return dataBase.update(table, values, whereClause, whereArgs);
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
return 0;
-
}
-
-
-
-
-
-
-
-
-
public Boolean isExistsById(String table, String id) {
-
try {
-
dataBase = dBManager.openDatabase();
-
return isExistsByField(table, mPrimaryKey, id);
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
return null;
-
}
-
-
-
-
-
-
-
-
public Boolean isExistsByField(String table, String field, String value) {
-
StringBuilder sql = new StringBuilder();
-
sql.append("SELECT COUNT(*) FROM ").append(table).append(" WHERE ")
-
.append(field).append(" =?");
-
try {
-
dataBase = dBManager.openDatabase();
-
return isExistsBySQL(sql.toString(), new String[] { value });
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(null);
-
}
-
}
-
return null;
-
}
-
-
-
-
-
-
-
-
-
public Boolean isExistsBySQL(String sql, String[] selectionArgs) {
-
Cursor cursor = null;
-
try {
-
dataBase = dBManager.openDatabase();
-
cursor = dataBase.rawQuery(sql, selectionArgs);
-
if (cursor.moveToFirst()) {
-
return (cursor.getInt(0) > 0);
-
} else {
-
return false;
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(cursor);
-
}
-
}
-
return null;
-
}
-
-
-
-
-
-
-
-
-
-
public <T> T queryForObject(RowMapper<T> rowMapper, String sql,
-
String[] args) {
-
Cursor cursor = null;
-
T object = null;
-
try {
-
dataBase = dBManager.openDatabase();
-
cursor = dataBase.rawQuery(sql, args);
-
if (cursor.moveToFirst()) {
-
object = rowMapper.mapRow(cursor, cursor.getCount());
-
}
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(cursor);
-
}
-
}
-
return object;
-
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
public <T> List<T> queryForList(RowMapper<T> rowMapper, String sql,
-
String[] selectionArgs) {
-
Cursor cursor = null;
-
List<T> list = null;
-
try {
-
dataBase = dBManager.openDatabase();
-
cursor = dataBase.rawQuery(sql, selectionArgs);
-
list = new ArrayList<T>();
-
while (cursor.moveToNext()) {
-
list.add(rowMapper.mapRow(cursor, cursor.getPosition()));
-
}
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(cursor);
-
}
-
}
-
return list;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
public <T> List<T> queryForList(RowMapper<T> rowMapper, String sql,
-
int startResult, int maxResult) {
-
Cursor cursor = null;
-
List<T> list = null;
-
try {
-
dataBase = dBManager.openDatabase();
-
cursor = dataBase.rawQuery(sql + " limit ?,?", new String[] {
-
String.valueOf(startResult), String.valueOf(maxResult) });
-
list = new ArrayList<T>();
-
while (cursor.moveToNext()) {
-
list.add(rowMapper.mapRow(cursor, cursor.getPosition()));
-
}
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(cursor);
-
}
-
}
-
return list;
-
}
-
-
-
-
-
-
-
public Integer getCount(String sql, String[] args) {
-
Cursor cursor = null;
-
try {
-
dataBase = dBManager.openDatabase();
-
cursor = dataBase.rawQuery("select count(*) from (" + sql + ")",
-
args);
-
if (cursor.moveToNext()) {
-
return cursor.getInt(0);
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(cursor);
-
}
-
}
-
return 0;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
public <T> List<T> queryForList(RowMapper<T> rowMapper, String table,
-
String[] columns, String selection, String[] selectionArgs,
-
String groupBy, String having, String orderBy, String limit) {
-
List<T> list = null;
-
Cursor cursor = null;
-
try {
-
dataBase = dBManager.openDatabase();
-
cursor = dataBase.query(table, columns, selection, selectionArgs,
-
groupBy, having, orderBy, limit);
-
list = new ArrayList<T>();
-
while (cursor.moveToNext()) {
-
list.add(rowMapper.mapRow(cursor, cursor.getPosition()));
-
}
-
} finally {
-
if (!isTransaction) {
-
closeDatabase(cursor);
-
}
-
}
-
return list;
-
}
-
-
-
-
-
-
-
public String getPrimaryKey() {
-
return mPrimaryKey;
-
}
-
-
-
-
-
-
-
public void setPrimaryKey(String primaryKey) {
-
this.mPrimaryKey = primaryKey;
-
}
-
-
-
-
-
-
-
-
public interface RowMapper<T> {
-
-
-
-
-
-
-
-
-
public T mapRow(Cursor cursor, int index);
-
}
-
-
-
-
-
public void closeDatabase(Cursor cursor) {
-
if (null != dataBase) {
-
dataBase.close();
-
}
-
if (null != cursor) {
-
cursor.close();
-
}
-
}
-
}
我们希望在android操作数据库是优雅的一种方式,这里不必关注事务,也不用担心分页,更不用为了封装传递对象烦恼,总之一切就像面向对象那样,简单,模板类的出现正是解决这个问题,虽然它看上去可能不是那么完美有待提高,这里我封装了很多sqlite常用的工具,大家可以借鉴使用。
3.XmppConnectionManager管理类
-
package csdn.shimiso.eim.manager;
-
-
import org.jivesoftware.smack.Connection;
-
import org.jivesoftware.smack.ConnectionConfiguration;
-
import org.jivesoftware.smack.Roster;
-
import org.jivesoftware.smack.XMPPConnection;
-
import org.jivesoftware.smack.provider.ProviderManager;
-
import org.jivesoftware.smackx.GroupChatInvitation;
-
import org.jivesoftware.smackx.PrivateDataManager;
-
import org.jivesoftware.smackx.packet.ChatStateExtension;
-
import org.jivesoftware.smackx.packet.LastActivity;
-
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
-
import org.jivesoftware.smackx.packet.OfflineMessageRequest;
-
import org.jivesoftware.smackx.packet.SharedGroupsInfo;
-
import org.jivesoftware.smackx.provider.DataFormProvider;
-
import org.jivesoftware.smackx.provider.DelayInformationProvider;
-
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
-
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
-
import org.jivesoftware.smackx.provider.MUCAdminProvider;
-
import org.jivesoftware.smackx.provider.MUCOwnerProvider;
-
import org.jivesoftware.smackx.provider.MUCUserProvider;
-
import org.jivesoftware.smackx.provider.MessageEventProvider;
-
import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
-
import org.jivesoftware.smackx.provider.RosterExchangeProvider;
-
import org.jivesoftware.smackx.provider.StreamInitiationProvider;
-
import org.jivesoftware.smackx.provider.VCardProvider;
-
import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
-
import org.jivesoftware.smackx.search.UserSearch;
-
-
import csdn.shimiso.eim.model.LoginConfig;
-
-
-
-
-
-
-
-
public class XmppConnectionManager {
-
private XMPPConnection connection;
-
private static ConnectionConfiguration connectionConfig;
-
private static XmppConnectionManager xmppConnectionManager;
-
-
private XmppConnectionManager() {
-
-
}
-
-
public static XmppConnectionManager getInstance() {
-
if (xmppConnectionManager == null) {
-
xmppConnectionManager = new XmppConnectionManager();
-
}
-
return xmppConnectionManager;
-
}
-
-
-
public XMPPConnection init(LoginConfig loginConfig) {
-
Connection.DEBUG_ENABLED = false;
-
ProviderManager pm = ProviderManager.getInstance();
-
configure(pm);
-
-
connectionConfig = new ConnectionConfiguration(
-
loginConfig.getXmppHost(), loginConfig.getXmppPort(),
-
loginConfig.getXmppServiceName());
-
connectionConfig.setSASLAuthenticationEnabled(false);
-
connectionConfig
-
.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
-
-
connectionConfig.setReconnectionAllowed(false);
-
-
connectionConfig.setSendPresence(true);
-
-
Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.manual);
-
connection = new XMPPConnection(connectionConfig);
-
return connection;
-
}
-
-
-
-
-
-
-
-
-
-
public XMPPConnection getConnection() {
-
if (connection == null) {
-
throw new RuntimeException("请先初始化XMPPConnection连接");
-
}
-
return connection;
-
}
-
-
-
-
-
-
-
-
-
public void disconnect() {
-
if (connection != null) {
-
connection.disconnect();
-
}
-
}
-
-
public void configure(ProviderManager pm) {
-
-
-
pm.addIQProvider("query", "jabber:iq:private",
-
new PrivateDataManager.PrivateDataIQProvider());
-
-
-
try {
-
pm.addIQProvider("query", "jabber:iq:time",
-
Class.forName("org.jivesoftware.smackx.packet.Time"));
-
} catch (ClassNotFoundException e) {
-
}
-
-
-
pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im",
-
new XHTMLExtensionProvider());
-
-
-
pm.addExtensionProvider("x", "jabber:x:roster",
-
new RosterExchangeProvider());
-
-
pm.addExtensionProvider("x", "jabber:x:event",
-
new MessageEventProvider());
-
-
pm.addExtensionProvider("active",
-
"http://jabber.org/protocol/chatstates",
-
new ChatStateExtension.Provider());
-
pm.addExtensionProvider("composing",
-
"http://jabber.org/protocol/chatstates",
-
new ChatStateExtension.Provider());
-
pm.addExtensionProvider("paused",
-
"http://jabber.org/protocol/chatstates",
-
new ChatStateExtension.Provider());
-
pm.addExtensionProvider("inactive",
-
"http://jabber.org/protocol/chatstates",
-
new ChatStateExtension.Provider());
-
pm.addExtensionProvider("gone",
-
"http://jabber.org/protocol/chatstates",
-
new ChatStateExtension.Provider());
-
-
-
pm.addIQProvider("si", "http://jabber.org/protocol/si",
-
new StreamInitiationProvider());
-
-
-
pm.addExtensionProvider("x", "jabber:x:conference",
-
new GroupChatInvitation.Provider());
-
-
pm.addIQProvider("query", "http://jabber.org/protocol/disco#items",
-
new DiscoverItemsProvider());
-
-
pm.addIQProvider("query", "http://jabber.org/protocol/disco#info",
-
new DiscoverInfoProvider());
-
-
pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());
-
-
pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user",
-
new MUCUserProvider());
-
-
pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin",
-
new MUCAdminProvider());
-
-
pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner",
-
new MUCOwnerProvider());
-
-
pm.addExtensionProvider("x", "jabber:x:delay",
-
new DelayInformationProvider());
-
-
try {
-
pm.addIQProvider("query", "jabber:iq:version",
-
Class.forName("org.jivesoftware.smackx.packet.Version"));
-
} catch (ClassNotFoundException e) {
-
}
-
-
pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());
-
-
pm.addIQProvider("offline", "http://jabber.org/protocol/offline",
-
new OfflineMessageRequest.Provider());
-
-
pm.addExtensionProvider("offline",
-
"http://jabber.org/protocol/offline",
-
new OfflineMessageInfo.Provider());
-
-
pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider());
-
-
pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider());
-
-
pm.addIQProvider("sharedgroup",
-
"http://www.jivesoftware.org/protocol/sharedgroup",
-
new SharedGroupsInfo.Provider());
-
-
pm.addExtensionProvider("addresses",
-
"http://jabber.org/protocol/address",
-
new MultipleAddressesProvider());
-
-
}
-
}
这个类是xmpp连接的管理类,如果大家使用smack的api对这个应该不会陌生,asmack对xmpp连接的管理,与smack的差别不大,但是部分细微区别也有,我们在使用中如果遇到问题,还要多加注意,我们这里将其设计成单例,毕竟重复创建连接是个非常消耗的过程。
很像QQ吧,没错,这是2012年版本qq的安卓界面,只是界面元素一样,实现方式大不相同,下面简单列一下这个客户端实现的功能:
1.聊天
2.离线消息
3.添加,删除好友
4.添加,移动好友分组
5.设置昵称
6.监控好友状态
7.网络断开系统自动重连接
8.收到添加好友请求消息处理
9.收到系统广播消息处理
10.查看历史聊天记录
11.消息弹出提醒,和小气泡
....
因为时间关系不是很完美,主要用于学习研究,欢迎大家给我提bug和改进意见。
分数比较大,不是为了坑大家,是怕有伸手党出现,拿了源码出去招摇撞骗,请尊重作者原创!
http://download.csdn.net/detail/shimiso/6224163