在做手机应用程序开发的时候,我们经常需要手动建立GPRS连接,下面我提供一个经过简单改动过的GPRS连接类。
这个类核心的代码,在网上都可以找到,我只是在这个基础上,进行了简单的封装,让他可以在后台自动监视连接,在连接断开的时候,可以自动建立,让我们在做业务逻辑的时候,可以不必去管GPRS连接着一块。
/// <summary> /// GPRS自动连接服务 /// </summary> public class ConnectionBLL { private static ConnectionBLL _ConnectionBLL = null; private bool _autoConnect = false; private int _interval = 30000; private ConnectState _connectState; private ConnectionBLL() { } public static ConnectionBLL Instance { get { if (_ConnectionBLL == null) { lock (typeof(ConnectionBLL)) { if (_ConnectionBLL == null) { _ConnectionBLL = new ConnectionBLL(); } } } return _ConnectionBLL; } } /// <summary> /// 连接状态 /// </summary> public ConnectState ConnectState { get { return _connectState; } } /// <summary> /// 是否自动连接 /// </summary> public bool AutoConnect { get { return _autoConnect; } } /// <summary> /// 监听频率 /// </summary> public int Interval { get { return _interval; } set { _interval = value; } } const int S_OK = 0; const uint CONNMGR_PARAM_GUIDDESTNET = 0x1; const uint CONNMGR_PRIORITY_USERINTERACTIVE = 0x08000; const uint INFINITE = 0xffffffff; const uint CONNMGR_STATUS_CONNECTED = 0x10; const int CONNMGR_MAX_DESC = 128; // @constdefine Max size of a network description const int CONNMGR_FLAG_PROXY_HTTP = 0x1; // @constdefine HTTP Proxy supported const int CONNMGR_FLAG_PROXY_WAP = 0x2; // @constdefine WAP Proxy (gateway) supported const int CONNMGR_FLAG_PROXY_SOCKS4 = 0x4; // @constdefine SOCKS4 Proxy supported const int CONNMGR_FLAG_PROXY_SOCKS5 = 0x8; // @constdefine SOCKS5 Proxy supported const UInt16 IDC_WAIT = 32514; const UInt16 IDC_ARROW = 32512; private IntPtr m_hConnection = IntPtr.Zero; public enum ConnMgrStatus { AuthenticationFailed = 0x2b, Connected = 0x10, ConnectionCanceled = 0x22, ConnectionDisabled = 0x23, ConnectionFailed = 0x21, ConnectionLinkFailed = 0x2a, Disconnected = 0x20, ExclusiveConflict = 40, NoPathToDestination = 0x24, NoPathWithProperty = 0x2c, NoResources = 0x29, PhoneOff = 0x27, Suspended = 0x11, Unknown = 0, WaitingConnection = 0x40, WaitingConnectionAbort = 0x81, WaitingDisconnection = 0x80, WaitingForNetwork = 0x42, WaitingForPath = 0x25, WaitingForPhone = 0x26, WaitingForResource = 0x41 } public ConnectionBLL() { } ~ConnectionBLL() { ReleaseConnection(); } /// <summary> /// 开始连接 /// </summary> public void Start() { try { if (!_autoConnect) { _autoConnect = true; ThreadPool.QueueUserWorkItem(new WaitCallback(Connect)); } } catch { } } /// <summary> /// 停止 /// </summary> public void Stop() { try { _autoConnect = false; this.ReleaseConnection(); _connectState = ConnectState.DisConnect; _ConnectionBLL = null; } catch { } } /// <summary> /// 连接 /// </summary> private void Connect(object obj) { while (this.AutoConnect) { uint status = 0; bool result = false; if (m_hConnection != IntPtr.Zero) { result = WaitForConnected(10, ref status); } if (!result) { _connectState = ConnectState.DisConnect; //枚举连接 List<CONNMGR_DESTINATION_INFO> lst = EnumConnDestinations(); for (int i = 0; i < lst.Count; i++) { string str = lst[i].Description; if (str.ToUpper().IndexOf("CMNET") > -1 || str.ToUpper().IndexOf("CMWAP") > -1) { if (EstablishConnection((uint)i)) { _connectState = ConnectState.Connected; break; } } } } else { _connectState = ConnectState.Connected; } Thread.Sleep(_interval); } } /// <summary> /// 枚举网络标识符信息 /// </summary> /// <param name="lstNetIdentifiers"></param> public List<CONNMGR_DESTINATION_INFO> EnumConnDestinations() { List<CONNMGR_DESTINATION_INFO> lstNetIdentifiers = new List<CONNMGR_DESTINATION_INFO>(); // 得到网络列表 for (uint dwEnumIndex = 0; ; dwEnumIndex++) { CONNMGR_DESTINATION_INFO networkDestInfo = new CONNMGR_DESTINATION_INFO(); if (ConnMgrEnumDestinations((int)dwEnumIndex, ref networkDestInfo) != 0) { break; } lstNetIdentifiers.Add(networkDestInfo); } return lstNetIdentifiers; } /// <summary> /// 建立连接 /// </summary> /// <param name="nIndex"></param> /// <returns></returns> public bool EstablishConnection(uint nIndex) { ReleaseConnection(); // 得到正确的连接信息 CONNMGR_DESTINATION_INFO DestInfo = new CONNMGR_DESTINATION_INFO(); int hResult = ConnMgrEnumDestinations((int)nIndex, ref DestInfo); if (hResult >= 0) { // 初始化连接结构 CONNMGR_CONNECTIONINFO ConnInfo = new CONNMGR_CONNECTIONINFO(); ConnInfo.cbSize = (uint)Marshal.SizeOf(ConnInfo); ConnInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET; ConnInfo.dwFlags = CONNMGR_FLAG_PROXY_HTTP | CONNMGR_FLAG_PROXY_WAP | CONNMGR_FLAG_PROXY_SOCKS4 | CONNMGR_FLAG_PROXY_SOCKS5; ConnInfo.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE; ConnInfo.guidDestNet = DestInfo.DestID; ConnInfo.bExclusive = 1; ConnInfo.bDisabled = 0; uint dwStatus = 0; hResult = ConnMgrEstablishConnectionSync(ref ConnInfo, ref m_hConnection, 10 * 1000, ref dwStatus); if (hResult < 0) { return false; } else { return true; } } return false; } /// <summary> /// 连接状态 /// </summary> /// <param name="nTimeoutSec"></param> /// <param name="pdwStatus"></param> /// <returns></returns> public bool WaitForConnected(int nTimeoutSec, ref uint pdwStatus) { uint dwStartTime = GetTickCount(); bool bRet = false; while (GetTickCount() - dwStartTime < (uint)nTimeoutSec * 1000) { if (m_hConnection.ToInt32() != 0) { uint dwStatus = 0; int hr = ConnMgrConnectionStatus(m_hConnection, ref dwStatus); if (dwStatus != 0) pdwStatus = dwStatus; if (hr >= 0) { if (dwStatus == CONNMGR_STATUS_CONNECTED) { bRet = true; break; } } } Thread.Sleep(100); } return bRet; } /// <summary> /// 释放所有连接 /// </summary> public void ReleaseConnection() { if (m_hConnection.ToInt32() != 0) { ConnMgrReleaseConnection(m_hConnection, 0); m_hConnection = IntPtr.Zero; } } [StructLayout(LayoutKind.Sequential)] public struct CONNMGR_CONNECTIONINFO { public uint cbSize; public uint dwParams; public uint dwFlags; public uint dwPriority; public int bExclusive; public int bDisabled; public GUID guidDestNet; public IntPtr hWnd; public uint uMsg; public uint lParam; public uint ulMaxCost; public uint ulMinRcvBw; public uint ulMaxConnLatency; } /// <summary> /// 此结构的内容对应:注册表中: /// </summary> [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct CONNMGR_DESTINATION_INFO { public GUID DestID; // @field GUID associated with network [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CONNMGR_MAX_DESC)] public string Description; // @field Description of network public int Secure; // @field Is it OK to allow multi-homing on the network } public struct GUID { // size is 16 public uint Data1; public UInt16 Data2; public UInt16 Data3; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] Data4; } [DllImport("coredll.dll")] public static extern uint GetTickCount(); [DllImport("coredll.dll")] public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); [DllImport("cellcore.dll")] public static extern int ConnMgrMapURL(string pwszURL, ref GUID pguid, ref uint pdwIndex); [DllImport("cellcore.dll")] public static extern int ConnMgrEstablishConnectionSync(ref CONNMGR_CONNECTIONINFO ci, ref IntPtr phConnection, uint dwTimeout, ref uint pdwStatus); [DllImport("cellcore.dll")] private static extern IntPtr ConnMgrApiReadyEvent(); [DllImport("cellcore.dll")] public static extern int ConnMgrReleaseConnection(IntPtr hConnection, int bCache); [DllImport("cellcore.dll")] public static extern int ConnMgrEnumDestinations(int nIndex, ref CONNMGR_DESTINATION_INFO pDestInfo); [DllImport("cellcore.dll")] public static extern int ConnMgrConnectionStatus(IntPtr hConnection, // @parm Handle to connection, returned from ConnMgrEstablishConnection ref uint pdwStatus // @parm Returns current connection status, one of CONNMGR_STATUS_* ); [DllImport("coredll.dll")] private static extern int CloseHandle(IntPtr hObject); } /// <summary> /// 连接状态 /// </summary> public enum ConnectState { /// <summary> /// 断开 /// </summary> DisConnect = 0, /// <summary> /// 已连接 /// </summary> Connected = 2 }
注意:为了加快连接速度,这里指定了连接移动的CMNET和CMWAP,可以根据需要修改,也可以不指定。