作者: 王恒进

1. BlackBerry 上连接 HTTPSocket 的五种方式

BlackBerry JDE 的 API 提供了五种方式来进行 HTTP 或者 socket 连接,包括:

1.1.        BlackBerry Enterprise Server(BES)方式

这种方式通过使用 BES 的 BlackBerry MDS Services 来进行网络连接,BlackBerry

MDS Services 负责处理所有的浏览器请求或者连接请求、并负责数据加密,这是黑莓 手机的默认连接方式,如下:

例 1:  (HttpConnection) Connector.open("http://www.testserver.com");

以上代码会自动将 BlackBerry MDS Services 作为它的默认连接路径。实际开发中, 如果要确保应用程序使用 uses BlackBerry MDS Services 作为它的连接路径,需要在 URL 最后加上参数“deviceside=false”,这也是我们推荐的方式,如下:

例 2:  (HttpConnection)Connector.open(“http://www.testserver.com;deviceside=false”);

1.2.       BlackBerry Internet ServieBIS)方式

这种方式是为第三方提供的连接接口,它对数据不进行加密,用户可以通过使用

HTTPS 和 SSL 来进行安全的连接。注:目前仅对加入了 BlackBerry Alliance Program

的第三方开放合作伙伴开放,详情参考:

http://na.blackberry.com/eng/partners/alliance.jsp

1.3.       Direct TCP 方式

这种方式允许在没有使用 BlackBerry MDS 的黑莓手机上直接 TCP 连接。为了能启用 direct TCP 方式,用户需要在手机的“选项-高级选项-TCP/IP”中设置 APN,以及相 应的用户名和密码。

注 1:运行在 iDEN 网络上的黑莓手机(包括 6510、7510、7520 和 7100i),如果不指

定 deviceside 参数(如例 1),默认的连接是 direct TCP;非运行在 iDEN 网络上的其 他黑莓手机,如果不指定 deviceside 参数,默认的连接是 BlackBerry MDS。

注 2:如果连接时 BlackBerry MDS 不存在,黑莓手机也会自动采用 direct TCP 方 式。

因此,如果要将 direct TCP 作为黑莓手机的默认连接方式,我们建议在 URL 中加入

deviceside=true”参数,如下:

例 3-1:  (SocketConnection)Connector.open("socket://testserver:600;deviceside=true");

此外,如果应用程序不希使用用户自己设置的 APN,也可以在 URL 中指定自己

APN,以下是指定通过中国移动 CMNET 进行直接 TCP 连接的例子:

例 3-2:  (SocketConnection)Connector.open("socket://testserver:600;deviceside=true;APN=cmnet");

1.4.       Wi-Fi

如果需要在 Wi-Fi 上创建网络连接,不需要在应用程序中考虑特别的底层逻辑,可以在

URL 中加入参数“interface=wifi”就能实现 Wi-Fi 连接,如下:

例 4:(StreamConnection)Connector.open(“socket:// testserver:600;interface=wifi”);

1.5.       WAP

1.5.1. WAP 1.x

并不是所有的移动运营商都支持通过 WAP 网关进行连接的,所以如果要创建 WAP 连 接,开发者需要和移动运营商联系,获取是否提供这种支持、并且获取他们的 WAP 网 管参数。

以下是一个基于中国移动 CMWAP 的 WAP 网关进行 HTTP 连接的例子:

例 5:

(HttpConnection)Connector.open("http://wap.google.com;WAPGatewayIP=10.0.0.172;WAPGatewayAPN=cm wap");

注:其中 WAPGatewayIPWAPGatewayAPN 这两项参数必须指定,参数之间用

“;”隔开,以下是所有的 WAP 参数列表,实际开发时请根据运营商提供的信息决定 哪些参数需要设置。

Parameter

Description

WapGatewayIP

IP address of the gateway.

WapGatewayAPN

APN for General Packet Radio Service (GPRS) networks only. For testing purposes, you can use rim.net.gprs

WapGatewayPort

Gateway port value. If port 9203 is specified, Wireless Transport Layer Security (WTLS) is used unless WapEnableWTLS=false is specified.

WapSourceIP

IP address of the source.

WapSourcePort

Source port value.

TunnelAuthUsername

User name for APN session, when Password Authentication

Protocol (PAP) or Challenge Handshake Application Protocol

(CHAP) authentication is used.

TunnelAuthPassword

Password for APN session, when PAP or CHAP

authentication is used.

WapEnableWTLS

Explicitly turns on or turns off WTLS. If this parameter is not specified, WTLS is used by default for connections to port

9203.

1.5.2. WAP 2.0

如果要连接 WAP2.0 的网关,需要在连接时指定 service record、以及 UID。以下代码说明

了 WAP2.0 的连接时如何工作的:

例 5:

ServiceBook sb = ServiceBook.getSB();

ServiceRecord[] records = sb.findRecordsByCid("WPTCP"); String uid = null;

for(int i=0; i < records.length; i++)

{

//Search through all service records to find the

//valid non-Wi-Fi and non-MMS

//WAP 2.0 Gateway Service Record.

if (records[i].isValid() && !records[i].isDisabled())

{

if (records[i].getUid() != null && records[i].getUid().length() != 0)

{

if ((records[i].getUid().toLowerCase().indexOf("wifi") == -1) &&

(records[i].getUid().toLowerCase().indexOf("mms") == -1))

{

uid = records[i].getUid();

break;

}

}

}

}

if (uid != null)

{

//open a WAP 2 connection

Connector.open(_url + ";ConnectionUID=" + uid);

}

else

{

//Consider another transport or alternative action.

}

在这里,基本流程是先从 Service Book 中获得 Service Record,然后再从中获得 UID,

后文会对此进行更具体的分析。

2. BlackBerry 上中国移动的 WAP 网关连接技巧

首先解释一下,中国移动提供 CMNET 和 CMWAP 两个 APN,本质上,这两个 APN 其实本应没 有区别,但是运营商从商业角度出发,从以下两方面来定位这二者:

1,采用不同的计费方式,不包月的情况下,CMNET 有可能收费更高

2,网络接入的授权不同,CMNET 能获得完全网络访问,就如 PC 直接上网一样,而 CMWAP

只能限制在 WAP(基本上可以等同于 HTTP,也就是只能访问 web service)

那么接下来,看黑莓上这两个 APN 有什么区别呢,显然,连 CMNET 能干更多的事,比如:

1, 长连接

2, 对端口的 socket 连接

而 CMWAP 由于计费便宜,因此用户可能的话,往往倾向于用这个 APN。不少应用为了达到 更好的体验,也将自己的应用首选或者甚至绑定 CMWAP 方式。

最后,来罗列一下中国移动的 WAP 情况下,有哪些连接方式。

WAP 1.x(国内的开发者,特别是从 J2ME 转过来的开发者,往往倾向于此)

1,  长连接或者 socket 连接 建议用:

(SocketConnection)Connector.open("socket://testserver:600;deviceside=true;APN=

cmnet");

如果在选项-高级-TCP/IP 中填上了 CMNET,用下面这种方式也能成功

(SocketConnection)Connector.open("socket://testserver:600;deviceside=true");

2,  用 CMWAP 访问 WAP 网站

(HttpConnection)Connector.open(http://wap.google.com;WAPGatewayIP=10.0.0.172;W APGatewayAPN=cmwap);

这里,注意不要写“WapGatewayPort=80”(似乎很多人都容易犯这个错误),原因是系

统会根据关键字 http 自动识别应该用哪个网关端口,实际上在黑莓上这个值也不是 80, 而是 9201

3,  用 CMNET 访问 WAP 网站

(HttpConnection)Connector.open(http://wap.google.com;WAPGatewayIP=10.0.0.172;W APGatewayAPN=cmnet );

或用 CMNET 访问任意网站

(HttpConnection)Connector.open( http://www.google.com;deviceside=true;APN=cmne

t )

WAP 2.0 方式(这是我强烈推荐的)

可能大家也发现了,用 WAP1.x 非常之不灵活,代码也往往会变得很复杂很乱。 而其实黑莓上有更好更简洁的办法,就是通过 WAP 2.0 来访问,在上一节里面写了一个例

子,来说明如何通过 WAP2.0 接入网络。在这里解释一下:

打开选项-高级选项-服务预订中,能看到一项叫做 WAP2 Transport[WPTCP],点进去可以 看到以下信息

名称:  WAP2 Transport

UID:  WAP2 trans

CID:     WPTCP

这些信息从哪里来的呢,这是黑莓上面的一个概念叫做 service book,每一项 service

book 其实就是一套对手机服务进行描述的配置文件,在这里的项目 RIM 和中国移动合作的 时候准备好的配置项,由黑莓手机上市前预加载、或者手机启动时由运营商将配置发送到 手机上。

就这一项而言,UID 是描述服务的关键词,CID 是描述服务走的是什么网络通道。UID 为

WAP2 trans 就表示这是 WAP2.0 的 service book,而且基本上这个关键词是不会变的。这 样就好理解了上一节中对 WAP2.0 那一段的代了。

其实有更简单的办法,用这个 URL 就直接达到效果了:

http://www.google.com;DeviceSide=true;ConnectionUID=WAP2 trans

3. BlackBerry 上中国电信的 WAP 网关连接分析

中国电信已经发布了 BlackBerry 9530,不同的是,这一款是烧号的,因此可以想象开发的时候还 是会遇到一些不同的。

1, C 网和 G 网的差别。中国电信的 CDMA,在 WAP 连接时没有 GPRS 上 APN 的概念。可是可能 有人要说,那么电信的“CTNET”和“CTWAP”是怎么一回事呢。其实这涉及到 CDMA 的底层, CDMA 是建立在 PPP 之上的,也就是手机拨号上网,那么可能经历过 modem 拨号年代的童鞋可能 还记得拨号的时候需要一个号码,还需要用户名和密码。那好,这里的 ctnet 和 ctwap 其实就是 这里的用户名。中国电信的服务端(一个叫做 PDSN 的东东)会对用户不同的用户名做配置,

ctwap 被授予的权限显然被限制在 WAP,而 CTNET 则能获得完全的 TCP/IP 的权限。通过这一手 段,达到了中国移动 cmnet 和 cmwap 类似的效果。为什么这么做呢,我觉得应该是商业模式吧, 让移动转来的用户能更快适应。在国外,通常没有这么复杂。

2,那么 9530 上如何上网呢。如果你打开选项-高级-TCP/IP,那么你会发现 APN 是不可改的,也 就是说你没法配置 CTNET 或者 CTWAP 之类的东东。那么可以猜想,RIM 应该和中国电信有一种 协议,9530 会自动的通过某种帐号上网。通过调试,我发现肯定不会是 CTNET,很可能是类似 CTWAP 的帐号。

最后,好了,现在电信上支持的网络连接方式总结如下:

1,如果你希望通过 WAP 上网,采用 WAP2.0 的方式

2,如果你希望能访问 TCP,只能采用 BES 的方式(虽然国内黑莓用户大多都是纯水货,没有开通 BES,但是在9530上没有这个问题,买到烧号的9530的,应该都通过中国电信开通了企业 服务)

4. BlackBerry 5.0 新提供的 Network API:自动选择网关的终

极解决方案

从前问来看,要想在 BlackBerry 上实现自动选择 WAP 来连接网络,似乎很复杂。但其实在

BlackBerry 5.0 上,这一切都已成为往事。随着 BlackBerry 5.0 的发布,其中包含了不少非常有用的

API,其中 Network API 就是用来提高网络编程效率的。Network API 包括以下类和接口:

包名:net.rim.device.api.io.transport

接口:

ConnectionAttemptListener This interface prescribes methods for a class that listens for connection attempts performed by a ConnectionFactory object.

类:

ConnectionDescriptor

This class stores information about a Connection opened by using a

ConnectionFactory.

ConnectionFactory      This class enables you to create HTTP, HTTPS, socket, TLS, and SSL

connections over supported transports.

TransportDescriptor    This class encapsulates information related to a specific transport instance.

TransportInfo               This class provides methods that provide information about the transport types available on a BlackBerry device.

其中的 ConnectionFactory 可以帮开发人员自动选择多种连接方式,也可以设置重试次数,自动支

持 HTTPS 和 SSL/TLS。以下是一个例子:

根据自动搜索,第一条发现的通道(由系统来决定)来建立 HTTP 连接:

// Create ConnectionFactory

ConnectionFactory factory = new ConnectionFactory();

// use the factory to get a connection

ConnectionDescriptor conDescriptor =

factory.getConnection("http://www.blackberry.com");//不设任何参数

if ( conDescriptor != null ) {

// connection succeeded int transportUsed =

conDescriptor.getTransportDescriptor().getTransportType();

// using the connection

HttpConnection    httpCon = (HttpConnection) conDescriptor.getConnection();

...

}

设定一个连接方式列表,按照预设定的优先顺序来建立 HTTP 连接:

// make a list of transport types ordered according to preference (they will be tried in succession)

int[] preferredTransportTypes = {TransportInfo.TRANSPORT_MDS, TransportInfo.TRANSPORT_WAP2};//连接方式列表,第一优先:BES 方式,第二优先:WAP2 方式

// Create ConnectionFactory

ConnectionFactory factory = new ConnectionFactory();

// Configure the factory

factory.setPreferredTransportTypes( preferredTransportTypes );

// use the factory to get a connection

ConnectionDescriptor conDescriptor =

factory.getConnection("http://www.blackberry.com");

if ( conDescriptor != null ) {

// connection suceeded

int transportUsed =

conDescriptor.getTransportDescriptor().getTransportType();

// using the connection

HttpConnection    httpCon = (HttpConnection) conDescriptor.getConnection();

...

}

设定一项特定的通道类型来建立 HTTP 连接:

// Create ConnectionFactory

ConnectionFactory factory = new ConnectionFactory();

// use the factory to get a connection

ConnectionDescriptor conDescriptor = factory.getConnection("http://www.blackberry.com", TransportInfo.TRANSPORT_WAP2, null);

if ( conDescriptor != null ) {

// connection over WAP2 succeeded

// using the connection

HttpConnection    httpCon = (HttpConnection) conDescriptor.getConnection();

...

}

设定一条具体的通道来建立 HTTP 连接:

// Create ConnectionFactory

ConnectionFactory factory = new ConnectionFactory();

// use the factory to get a connection

ConnectionDescriptor conDescriptor = factory.getConnection("http://www.blackberry.com", TransportInfo.TRANSPORT_MDS, "S109234");

if ( conDescriptor != null ) {

// connection to specific BES succeeded

// using the connection

HttpConnection    httpCon = (HttpConnection) conDescriptor.getConnection();

...

}

5. 网络设置解决方案举例 以上介绍了各种网络连接的代码实现,但是国内黑莓开发的初学者在设计的时候,最头疼的一个 问题就是网络设置。

BlackBerry 与其他手机不同的是,多了好几种联网方式,如何把这些整合在你的设置里面,让 用户自己来选择希望的联网通道。国外很多成熟的应用这方面早就已经很完美的解决了。

这里拿国外某股票软件做例子,网络连接上这个应用是基于 Socket 的,而非 HTTP。 我们首先来看它的设置首页,提供四种方式:BIS,BES,TCP,WiFi

补充介绍一下,这个软件底层是基于 TCP/IP 的,否则的话,如果是基于 WAP 的软件,通常应该

再加上 WAP 的 APN 的设置。
另外,根据实际情况,有的软件可能需要加上“自动选择网络”,并将其设为默认选项。

6.  HTTP 连接代码实例

以下这个例子不很完善,因为没有包括 WAP 和 WAP2 连接,但在前文已经做了很充分的 讨论,不过这段代码还是满足绝大部分情况下的需求,而且同时支持 GET 和 POST。

public static final int CONNECTION_DEFAULT = 0;

public static final int CONNECTION_BIS = 1; public static final int CONNECTION_BES = 2; public static final int CONNECTION_TCPIP = 3; public static final int CONNECTION_WIFI = 4;

public boolean get(String url) {

service(url, null);

}

public boolean post(String url, URLEncodedPostData postdata) {

service(url, postdata);

}

private boolean service(String url, URLEncodedPostData postdata) { HttpConnection con = null;

InputStream in = null;

try {

if (CoverageInfo.isOutOfCoverage())

return false;

byte[] data = null;

if (postdata != null) {

data = postdata.getBytes();

}

// If WLAN is active, try wlan

if ((RadioInfo.getActiveWAFs() & RadioInfo.WAF_WLAN) != 0) {

try {

if (CoverageInfo.isCoverageSufficient( CoverageInfo.COVERAGE_CARRIER, RadioInfo.WAF_WLAN, false))

{

con = HttpUtils.makeHttpConnection(

url, new HttpHeaders(), data, CONNECTION_WIFI);

con.getResponseCode();

}

} catch (Exception ex) { Log.error("UP.R.WF: " + ex); con = null;

}

}

// Otherwise try the preferred connection type. if (con == null) {

try {

con = HttpUtils.makeHttpConnection(

url, new HttpHeaders(), data, IOPreferences.getPreferredConnectionType());

con.getResponseCode();

} catch (Exception ex) { Log.error("UP.R1: " + ex); con = null;

}

}

if (con == null) {

// If preferred type doesnot work, find something else. int ctype = getCoverageBasedConnectionType();

if (ctype >= 0) {

try {

con = HttpUtils.makeHttpConnection(url, new HttpHeaders(), data, ctype);

con.getResponseCode();

} catch (Exception ex) { Log.error("UP.R2: " + ex); con = null;

}

}

}

int respcode = con.getResponseCode();

// You can handle HTTP_MOVED_* here if you want to

// We don't because we  connect to our own servers

if (respcode == HttpConnection.HTTP_OK) {

in = con.openInputStream();

// Handle incoming data handleData(con, in);

return true;

}

} catch (Exception e) { Log.error("UP.R() : " + e);

} finally {

close(con, in);

}

return false;

}

protected abstract void handleData(HttpConnection con, InputStream in);

private static void close(HttpConnection con, InputStream in) {

if (in != null) {

try {

in.close();

} catch (IOException e2) {

}

}

if (con != null) { try { con.close();

} catch (IOException e) {

}

}

}

public static int getCoverageBasedConnectionType() {

if (CoverageInfo.isCoverageSufficient(CoverageInfoProxy.COVERAGE_CARRIER, RadioInfo.WAF_WLAN))

{

return IOConstants.CONNECTION_WIFI;

}

if (CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_BIS_B)) {

return IOConstants.CONNECTION_BIS;

}

if (CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_MDS)) {

return IOConstants.CONNECTION_BES;

}

return IOConstants.CONNECTION_DEFAULT;

}

Finally the method to make the http connection class HttpUtils {

public static final int CONNECTION_DEFAULT = 0;

public static final int CONNECTION_BIS = 1; public static final int CONNECTION_BES = 2; public static final int CONNECTION_TCPIP = 3; public static final int CONNECTION_WIFI = 4;

/**

* This method opens a HTTP connection to the given url. The method used is

* GET or POST depending on whether postData is null or not. Only the

* provided connType is used. For example, if the connType is

* CONNECTION_BES, the connection is tried using the BES only.

* The only time provided connection type is not used is when the URL

* contains ";deviceside=".

*

* @param url

*             The url to connect to.

* @param requestHeaders

*             The headers in the request. May be null or empty.

* @param postData

*             Data to be posted to the server. If null, the GET method used

*             for the http connection.

* @param connType

*             The type of transport (BES / BIS / WIFI / Default) to be used

*             for opening connection.

* @return Opened HttpConnection object or null if some error occurs.

*/

public static HttpConnection makeHttpConnection(String url, HttpHeaders requestHeaders, byte[] postData, int connType) {

HttpConnection conn = null; OutputStream out = null;

if (StringUtilities.startsWithIgnoreCase(url, "www.")) {

url = "http://" + url;

}

try {

if (url.indexOf(";deviceside=") == -1) {

switch (connType) {

case CONNECTION_BES:

url = url + ";deviceside=false";

break;

case CONNECTION_BIS:

url = url + ";XXXXXXXXXXXXXXXX";

break;

case CONNECTION_TCPIP:

url = url + ";deviceside=true";

break;

case CONNECTION_WIFI:

url = url + ";interface=wifi";

}

}

conn = (HttpConnection) Connector.open(url);

if (requestHeaders != null) {

String referer = requestHeaders.getPropertyValue("referer");

boolean sendReferrer = true;

if (referer != null && StringUtilities.startsWithIgnoreCase(referer, "https:") &&

!StringUtilities.startsWithIgnoreCase(url, "https:")) {

sendReferrer = false;

}

int size = requestHeaders.size();

for (int i = 0; i < size;) {

String header = requestHeaders.getPropertyKey(i);

// remove header if needed

if (!sendReferrer && header.equals("referer")) {

requestHeaders.removeProperty(i);

--size;

continue;

}

String value = requestHeaders.getPropertyValue(i++);

if (value != null) {

conn.setRequestProperty(header, value);

}

}

}

if (postData == null) { conn.setRequestMethod(HttpConnection.GET); conn.setRequestProperty("User-Agent",

"Profile/MIDP-2.0 Configuration/CLDC-1.0");

} else { conn.setRequestMethod(HttpConnection.POST); conn.setRequestProperty(

HttpProtocolConstants.HEADER_CONTENT_LENGTH,

String.valueOf(postData.length));

conn.setRequestProperty("Content-Type",

"application/x-www-form-urlencoded");

conn.setRequestProperty("User-Agent",

"Profile/MIDP-2.0 Configuration/CLDC-1.0");

out = conn.openOutputStream();

out.write(postData);

out.flush();

}

} catch (IOException e1) { Log.error("UTIL.HTC " + e1);

close(conn, null); // Close the connection

conn = null;

} finally {

close(null, out); // Close the output, but keep connection open

}

return conn;

}

private static void close(HttpConnection con, OutputStream out) {

if (out != null) {

try {

out.close();

} catch (IOException e2) {

}

}

if (con != null) { try { con.close();

} catch (IOException e) {

}

}

}

}

 
 

BlackBerry SDK下载

  • BlackBerry Java Plug-in for Eclipse v1.1
  • Java Plug-in for Eclipse Update Site
  • BlackBerry Web Plug-in v2.0
  • BlackBerry Widget SDK v1.0
  • BlackBerry Theme Studio v5.0
  • Plazmic Content Developer’s Kit v4.7
  • BlackBerry smartphone simulators

BlackBerry 网络连接编程相关推荐

  1. 也谈BlackBerry网络连接

    也谈BlackBerry网络连接 注意事项: 1. CT的WAP 2网关只能访问HTTP协议,但是端口可以是任意,比如可以访问 http://m.baidu.com, http://crj.fjgat ...

  2. Android编程获取网络连接状态及调用网络配置界面

    获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityMan ...

  3. Android编程获取网络连接状态(3G/Wifi)及调用网络配置界面

    http://www.mobiletuts.me 获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. An ...

  4. android编程获取网络和wifi状态及调用网络设置界面,Android编程获取网络连接状态(3G/Wifi)及调用网络配置界面 - Android平台开发技术 - 博客园...

    获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityMan ...

  5. Android编程 获取网络连接状态 及调用网络配置界面

    获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityMan ...

  6. BlackBerry上连接HTTP或Socket的五种方式

    在blackberry的开发中,网络相关的设置有时候比较令人困惑,下面是一篇关于网络设置编程的文章 BlackBerry上连接HTTP或Socket的五种方式 BlackBerry 的API提供了五种 ...

  7. JAVA网络IO编程

    2019独角兽企业重金招聘Python工程师标准>>> JAVA网络IO编程(BIO NIO AIO) 一.传统的BIO编程 1.网络编程的基本模型是C/S模型,即两个进程间的通信. ...

  8. python3 socketserver模块 网络服务编程框架

    socket编程过于底层,编程虽然有套路,但是想要写出健壮的代码还是比较困难的,所以很多语言都对socket底层 API进行封装,Python的封装就是--socketserver模块.它是网络服务编 ...

  9. Android 网络连接--Wifi/3G

    获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityMan ...

最新文章

  1. SAP S/4HANA CDS View的访问控制实现:DCL介绍
  2. 使用敏捷回顾实施组织变革
  3. python3学习笔记10(迭代器和生成器)
  4. 「06」回归的诱惑:一文读懂线性回归(Python实战篇)
  5. java sql连接代码 sqlserver的jar包
  6. 进销存excel_excel进销存仓库表格同步手机操作
  7. Java基础学习总结(70)——开发Java项目常用的工具汇总
  8. 怎么用python制作随机点名软件_利用Python实现课堂点名器!辅导员大大的夸赞了我!...
  9. 【企业】奥卡姆剃刀定律,把握环境的价值
  10. python获取元素在数组中的位置
  11. 一键adb连接网易Mumu模拟器
  12. 商标45类分类表明细表_45类商标分类明细_45类商标经营范围包括哪些商品-商标查询-知夫子...
  13. 如何清除360网站服务器缓存,360安全浏览器怎样清除缓存360浏览器缓存清理
  14. JS 逆向之 Hook
  15. Android项目必备技术
  16. 公众平台服务号、订阅号、企业微信以及小程序的相关说明
  17. 流线动态图python_流的解释|流的意思|汉典“流”字的基本解释
  18. mongoDB的读书笔记(04)_【Replica】(01)_Replica的一些基本概念
  19. 恢复快速启动栏显示桌面按钮
  20. 软件测试——基础练习(期末复习)

热门文章

  1. 【转】让子弹飞—— “我受不了你那股子自信”
  2. html图片打印不出来 lodop_前端实现打印图像功能
  3. 自然语言处理—文本情感分析
  4. ANDROID ION_BUFFER
  5. JavaScript 字符串转日期多八个小时的解决
  6. RHCE模拟练习题整理
  7. JVM之垃圾回收算法详解
  8. 飞天软件锁Rockey1在软件产品中的应用
  9. 比较不错的Web工作流设计器
  10. iOS14-桌面小插件 IntentConfiguration