编程语言
首页 > 编程语言> > 读书笔记-Java网络编程安全教程-微课版

读书笔记-Java网络编程安全教程-微课版

作者:互联网

Java网络编程安全教程 清华大学出版社 ISBN-9787302482833

仅供参考, 自建索引, 以备后查

https://docs.oracle.com/javase/6/docs/api/index.html

https://docs.oracle.com/javase/7/docs/api/index.html

https://docs.oracle.com/javase/8/docs/api/index.html

=================================================================

一: 简介概述 IO流

java.io.*       java.nio.*       java.nio.channels.*

InputStream  OutputStream  字节流

Reader Writer  字符流

InputStreamReader  OutputStreamWriter  字节流与字符流转换

FileInputStream/FileOutputStream    二进制流

BufferedInputStream/BufferedOutputStream   二进制缓冲流

DataInputStream/DataOutputStream    数据流

 

HTTP/SMTP/POP3/FTP/Telnet/DHCP  应用层+表示层+会话层= *应用层

TCP/IP *传输层 + *网络层

MAC地址  数据链路层+物理层= *网络接口层

TCP-IP-OSI-协议栈模型

 

SOCKET是操作系统开放给程序员的网络编程接口

传输层以下协议的技术实现是由操作系统完成的,即网络服务由操作系统提供

SOCK_STREAM流式套接字  SOCK_DGRAM数据报套接字  SOCK_RAW原始套接字

通信端口  0~65535

 

线程:  新生new  等待系统分配CPU执行start   执行run   阻塞wait/sleep/join/yield   消亡throw/interrept/stop

ServerSocket/Socket   DatagramPacket/DatagramSocket

 

=================================================================

二: ServerSocket多线程与Client通信

ServerSocket ss = new ServerSocket();

ss.bind(..);

while (true) {

    Socket client = ss.accept();
    new ClientSocketHandlerThread(client).start();

}
Class ClientSocketHandlerThread implements Runnable {
    ClientSocketHandlerThread(Socket s) {
        // TODO
    }
    public void run() {
        // TODO
    }
}

SwingWorker<T,V> implements Runnable, Future<T>, RunnableFuture<T>

doInBackground()      publish()     process()    done()    get()

 

=================================================================

三: ServerSocket多线程与Client通信+线程池

最佳线程池大小 = Runtime.getRuntime().availableProcessors() * 2 + 1

int MAX = Runtime.getRuntime().availableProcessors() * 2 + 1;
ExecutorService fixedPool = Executors.newFixThreadPool(MAX);

ServerSocket ss = new ServerSocket();

ss.bind(..);

while (true) {

    Socket client = ss.accept();
    /// 在线程池中执行 
    fixedPool.exec( new ClientSocketHandlerThread(client) );

}
fixedPool.shutdown(); /// 等待线程池中所有线程执行完毕,此时已经不能再向线程池添加线程
if ( ! fixedPoo.awaitTermination(60, TimeUnit.SECONDS) ) {
    fixedPool.shutdownNow(); /// 如果60S还没结束则强制关闭
}

/ 下面是API文档的示例
The following method shuts down an ExecutorService in two phases, 
first by calling shutdown to reject incoming tasks, and then calling 
shutdownNow, if necessary, to cancel any lingering tasks:
 void shutdownAndAwaitTermination(ExecutorService pool) {
   pool.shutdown(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
 }

Executor

void execute(..)   无参数返回 

ExecutorService

Future<?> submit(..)  返回Future对象

T invokeAny(Collection<?>...)   执行一组任务,返回其中一个结果,通常情况下是最先执行完毕的那个

List<Future<?>> invokeAll(Collection<?>...)  返回所有任务的Future对象

更多线程、线程池参考 Java并发编程从入门到精通

 

=================================================================

四: 非阻塞I/ O NIO:(1)New I/O (2)Non-Blocking I/O

ServerSocket/Socket      ServerSocketChannel/SocketChannel

DatagramSocket/DatagramPacket     DatagramChannel

Selector/SelectionKey轮询机制

Buffer   ByteBuffer/CharBuffer/DoubleBuffer/FloatBuffer/IntBuffer/LongBuffer/ShortBuffer

allocate() [ˈæləkeɪt]  read()  write()  clear()  flip() [flɪp]  wrap() [ræp]  limit()

capacity() [kəˈpæsəti] reset()  rewind() [ˌriːˈwaɪnd]

Selector

SelectionKey

OP_ACCEPT=16  OP_CONNECT=8  OP_READ=1  OP_WRITE=4

支持多模式  OP_READ | OP_WRITE    (位与运算  参考 Linux 权限 124)

自定义协议类 <===============

/// 服务端代码,启动监听
Selector st = Selector.open();
ServerSocketChannel listen = ServerSocketChannel.open();
listen.socket().bind(..);
listen.configureBlocking(false); 
listen.register(st, SelectionKey.OP_ACCEPT);
/// register() 第三个参数 If the att argument is not null then 
/// the key's attachment will have been set to that value
/// listen.register(st, SelectionKey.OP_ACCEPT, new SelfDefinedProtocol());

while (true) {
    int nKeys = st.select();
    if (nKeys == 0) 
        continue; /// 
    Set<SelectionKey> keys = st.selectedKeys();
    keys.forEach(k->{
        // TODO
    });
}
/// Client端连接
SocketChannel sc = SocketChannel.open();
sc.connect(..);

Charset charset = Charset.forName("UTF-8");
ByteBuffer outBuff = ByteBuffer.wrap("要发送的内容".getBytes(charset));
sc.write(outBuff);

ByteBuffer inBuff = ByteBuffer.allocate(2048);
sc.read(inBuff);
inBuff.flip(); // postion=0
String content = charset.decode(inBuff).toString();

// TODO

IO流:阻塞机制; 多线程占用系统及CPU资源;

   readLine() 能确定当前文本行被读完

NIO:读到数据处理,否则立即返回; 采用轮询机制,单线程处理大量并发连接;

   缓冲区需要处理数据被分割的情况

 

NIO支持 分散(scatter) / 聚集(gather) 工作模式

SocketChannel sc = ..;
ByteBuffer header = ByteBuffer.allocate(60);
ByteBuffer body = ByteBuffer.allocate(2048);
ByteBuffer[] gather = { header, body };
sc.read(gather); /// 分散模式 scatter 把通道数据读到多个缓存中
sc.write(gather); /// 聚集模式 gather 多个数据写入到通道中

其它相关 <=============

public abstract int interestOps()

public abstract int readyOps()
public abstract SelectableChannel channel()
public abstract Selector selector()
public final Object attachment()

 

 

 

 

 

interestOps() 返回值即 register() 第二个参数 

int interestKey = selectionKey.interestOps();
boolean isAccept = interestSet & SelectioinKey.OP_ACCEPT != 0;
//                 interestSet & SelectionKey.OP_CONNECT;
//                 interestSet & SelectionKey.OP_READ
//                 interestSet & SelectionKey.OP_WRITE

/// 或者
selectionKey.isAcceptable();
selectionKey.isConnectable();
selectionKey.isReadable();
selectionKey.isWritable();

 

ServerSocketChannel channel = ServerSocketChannel.open();
channel.configureBlocking(false);
channel.bind(null); 
Selector selector = Selector.open();
channel.register(selector, 29);
while (true) {
	int nSize = selector.select();
	if (nSize == 0) {
		continue;
	}
	selector.selectedKeys().forEach(key -> {
		if (key.isAcceptable()) {
			// TODO 
		} 
		else if (key.isConnectable()) {
			// TODO
		}
		else if (key.isReadable()) {
			// TODO
		}
		else if (key.isWritable()) {
			// TODO
		}
	});
}

 

=================================================================

五: UDP

UDP报文结构

DatagramPacket 构造函数(接收、发送) 及 方法 

DatagramSocket 构造函数 及 方法   receive(..)  send(..)

对象序列化与反序列化

/// 对象序列化为字节数组
public static <T extends Serializable> byte[] objectTo(T obj) {
	try {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		ObjectOutputStream objOutput = new ObjectOutputStream(output);
		objOutput.writeObject(obj);
		return output.toByteArray();
	} catch (IOException e) {
		e.printStackTrace();
	}
	return null;
}
/// 字节数组反序列化为对象
public static Object toObject(byte[] bytes) {
	try {
		ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
		ObjectInputStream oin = new ObjectInputStream(bin);
		return oin.readObject();
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
	return null;
}
/// 发送数据
public static void sendTo(Serializable data, InetAddress remote, int port) {
	DatagramSocket socket = null;
	try {
		byte[] bytes = objectTo(data);
		socket = new DatagramSocket();
		socket.setSoTimeout(3000);
		DatagramPacket packet = new DatagramPacket(bytes, bytes.length, remote, port);
		socket.send(packet);
	} catch (SocketException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		if (socket != null)
			socket.close();
	}
}

UDP: DNS服务、DHCP服务、网络音视频点播

 

=================================================================

六: TCP传输文件

/// 选择文件
public static File getFile() {
	JFileChooser jfc = new JFileChooser();
	jfc.setDialogTitle("选择文件");
	jfc.setApproveButtonText("确认选择");
	if (jfc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
		return jfc.getSelectedFile();
	}
	return null;
}

SwingWorker<T,V>

T 在 doInBackground() 与 get() 方法中做返回类型

V 在 publish() 与 process() 方法中做要处理的数据类型

调用 execute() 方法,会自动启动线程执行 doInBackground() 方法,类似于

Thread类的 start() 方法会自动调用 run() 方法

事件调度线程 EDT Event Dispatch Thread

在 SwingWorker doInBackground() 执行完毕会调用 SwingWorker done() 方法

可以使用 isDone() 来检测是否执行完毕   也可以调用 get() 方法获取结果

若 doInBackground() 方法调用 publish(),则 EDT 会调用 SwingWorker process() 来更新UI

当前线程调用 SwingWorker execute() 方法立即返回,工作线程执行 doInBackground() ,

可以在其内部调用 publish() 更新进度,EDT(一般是主线程)调用后续方法 process() done(),

且可以监听 SwingWorker 的 PropertyChangeListener 事件

UDP 与 TCP 可以同时使用同一个端口且互不影响

 

=================================================================

七: SSL/TLS

SSL3.1 == TLS1.1    SSL3.2 == TLS1.1     SSL3.3 == TLS1.2

在 应用层 与 TCP传输层 之间加入 SSL/TLS协议层 

常用加密算法 

DES对称密钥  3DES  Blowfish  RC5

AES分组对称密钥  AES-128  AES-192 AES-256

RSA非对称密码算法  运算速度比对称密码算法慢

哈希摘要算法 MD5 Message Digest Algorithm 消息摘要算法 

    SHA-1(160位) SHA-256(256位) Secure Hash Algorithm 安全哈希算法

 

SSL/TLS协议基本工作原理

SSL/TLS协议基本工作原理

 

密钥生成工具 keytool       x.509证书

keytool -genkeypair  RSA 生成RSA非对称密钥

keytool -exportcert  从RSA非对称密钥中导出公钥

keytool -importcert  导入公钥到信任的密钥库中

 

JAVA 摘要算法使用 及 生成AES对称密钥

/// hashType in [ "MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512" ]
public static String getHash(String plainText, String hashType) {
	try {
		MessageDigest md = MessageDigest.getInstance(hashType);
		byte[] bytes = md.digest(plainText.getBytes("UTF-8"));
		return DatatypeConverter.printHexBinary(bytes);
	} catch (NoSuchAlgorithmException e) {
		e.printStackTrace();
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	}
	return null;
}
/// 生成256位AES对称密钥
public static SecretKey newKey() {
	try {
		KeyGenerator kg = KeyGenerator.getInstance("AES");
		kg.init(256);
		return kg.generateKey();
	} catch (NoSuchAlgorithmException e) {
		e.printStackTrace();
	}
	return null;
}

 

/// 向指定ServerSocket发送文件 读取需要按照以下顺序
/// long(文件长度) 
/// 文件byte[] 
/// int(AES对称密钥长度) 
/// 密钥byte[] 
/// int(文件摘要长度) 
/// 文件摘要byte[]
public void sendToWithSSL(String filePath, InetAddress remote, int port) throws Exception {
	/// 本机私钥 
	KeyStore privateKS = getKeyStore("/config/client.keystore", "pwd567");
	KeyManagerFactory privateKF = KeyManagerFactory.getInstance("SunX509");
	privateKF.init(privateKS, "pwd567".toCharArray());
	/// 其它机器发行的公钥
	KeyStore publicTKS = getKeyStore("/config/public.keystore", "899psw");
	TrustManagerFactory publicKF = TrustManagerFactory.getInstance("SunX509");
	publicKF.init(publicTKS);
	/// SSL/TLS上下文
	SSLContext ctx = SSLContext.getInstance("SSL");
	ctx.init(privateKF.getKeyManagers(), publicKF.getTrustManagers(), null);
	///
	/// 创建SSL环境下的Socket
	Socket socket = ctx.getSocketFactory().createSocket(remote, port);
	DataOutputStream sendOut = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
	File file = new File(filePath);
	sendOut.writeLong(file.length()); /// 文件长度
	sendOut.flush();
	/// 读取文件以便写到SOCKET中,并在完成后生成摘要信息
	MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
	DigestInputStream digestIn = new DigestInputStream(new BufferedInputStream(new FileInputStream(file)), sha256);
	/// 
	byte[] buf = new byte[2048];
	int temp = 0;
	while ( (temp = digestIn.read(buf)) != -1) {
		if (temp == 0) 
			continue;
		sendOut.write(buf, 0, temp);
		sendOut.flush();
	}
	digestIn.close();
	/// sendOut.close(); /// 此处还要关闭,之后还要写密钥信息
	/// 从输入流中获取文件摘要信息
	byte[] fileDigest = digestIn.getMessageDigest().digest();
	//String digestText = DatatypeConverter.printHexBinary(fileDigest);
	/// 加密文件摘要 当前机器私钥加密,需要用发行的公钥解密
	Key privateKey = privateKS.getKey("my_key", "pwd567".toCharArray());
	byte[] signature = doCipher("RSA/ECB/PKCS1Padding", privateKey, fileDigest);
	//String signatureText = DatatypeConverter.printHexBinary(signature);
	/// 我方公钥是公开发行,任何人均可使用公钥对其解密 所以对加密后的文件摘要再次做加密处理
	Key randomKey = newKey(); /// 随机对称密钥
	byte[] signatureAES = doCipher("AES", randomKey, signature);
	/// 再用对方的公钥把 使用的随机对称密钥 加密,对方用私钥可以解密 之后可以对文件摘要进行解密
	Key publicKey = publicTKS.getCertificate("server").getPublicKey();
	byte[] encryptedKey = doCipher("RSA/ECB/PKCS1Padding", publicKey, randomKey.getEncoded());
	/// 把密钥等发送
	sendOut.writeInt(encryptedKey.length);
	sendOut.flush();
	sendOut.write(encryptedKey);
	sendOut.flush();
	sendOut.writeInt(signatureAES.length);
	sendOut.flush();
	sendOut.write(signatureAES);
	sendOut.flush();
    sendOut.close();
}
/// 生成256位AES对称密钥
public static SecretKey newKey() {
	try {
		KeyGenerator kg = KeyGenerator.getInstance("AES");
		kg.init(256);
		return kg.generateKey();
	} catch (NoSuchAlgorithmException e) {
		e.printStackTrace();
	}
	return null;
}
/// 加密数据
private byte[] doCipher(String type, Key key, byte[] original) throws Exception {
	Cipher cipher = Cipher.getInstance(type); 
	cipher.init(Cipher.ENCRYPT_MODE, key);
	return cipher.doFinal(original);
}
/// 加载密钥库
private KeyStore getKeyStore(String path, String pwd) throws Exception {
	KeyStore ks = KeyStore.getInstance("JKS");
	InputStream stream = this.getClass().getResourceAsStream(path);
	ks.load(stream, pwd.toCharArray());
	return ks;
}

 

=================================================================

八: 网络抓包

Pcap4J 通过 JNA 对 libpcap(UNIX/Linux), WinPcap, Npcap 封装调用

WireShark 抓包工具基于 libpcap WinPcap 

数据传输中:  应用层数据  到达 传输层 会被加上 协议端口号,

到达 网络层 会被加上 IP头信息,设置源地址及目标地址, 

到达 网络链路层, IP地址映射为 MAC地址

到达 物理层, 数据为 二进制 

数据包解析协议:  帧头部MAC --- 网络层状况IP --- 传输层头部PORT --- 数据包

帧状况包含收发双方MAC地址

TCP头部20-60字节,无附加信息时20字节

IP状况20-60字节,无附加信息时20字节

TCP头部基本结构

IP头部基本结构

 

=================================================================

九: 邮件

SMTP: Simple Mail Transfer Protocol 简单邮件传输协议  默认端口25

ESMTP: Extension Simple Mail Transfer Protocol 加入安全认证功能

交互过程中   2** 表示命令执行成功   3** 等待用户输入    5** 命令执行失败

ehlo <name>     用于替代 helo

auth ****            回应SMTP服务器的验证方式

  e.g.    auth  login  ENTER

            {Base64编码的用户名}  ENTER

            {Base64编码的密码}  ENTER

mail from:<abc@qq.com> 

rcpt to:<def@163.com>

data                   SMTP服务器等待用户输入邮件内容

         邮件内容输入结束标志是 回车换行 输入 .  再回车换行

quit                    结束退出 

POP3/IMAP: 用于获取邮件列表数据

Post Office Protocol Version 3  端口110

Internet Mail Access Protocol Version4

JavaMail库  javax.mail.Message   javax.mail.Transport   javax.mail.Store  javax.mail.Session

 

=================================================================

十: WebSocket

javax.websocket.server

 @ServerEndpoint 标记类为 WebSocket 服务端

 @PathParam 用于动态参数,URI中及方法参数中均可

 @OnOpen 连接成功时触发的方法

 @OnMessage 服务端收到客户端的消息触发  查看源码示例给出标记方法的参数类型

 @OnClose  @OnError

在 pom.xml 加入库引用,可查看上述注解源码

<dependency>
   <groupId>javax.websocket</groupId>
   <artifactId>javax.websocket-api</artifactId>
   <version>1.1</version>
   <scope>provided</scope>
</dependency>

WebSocket 握手阶段的 HTTP 头信息

GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: ******  ///BASE64随机值
Sec-WebSocket-Version: **  ///WebSocket版本号

握手阶段响应

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ********

JS WebSocket 发送代码示例

// TODO

服务端 @ServerEndpoint 标记代码示例

// TODO

 

=================================================================

十一: Nodejs Socket.IO MongoDB HTML5语音

Nodejs 是 Javascript 在服务端的运行环境,采用谷歌 V8 引擎,内核由c++编写,主要

技术特点是事件驱动和非阻塞I/O       其在命令行模式下使用 REPL 和 .js 文件

REPL: Read, Evaluate, Print, Loop 输入 求值  输出  循环

模块加载  require('核心模块或第三方模块名称')  require('自定义模块路径')

npm: node package manage  

# npm -install -g ***      # npm install cnpm -g    # npm/cnpm install -g supervisor

package.json  模块、项目配置文件,必不可少   用 npm init 来生成


MongoDB: 基于分布式文件在售,在非关系数据库中最低关系型数据库。 

BJSON: Binary JSON     nodejs中可使用Mongoose来操作MongoDB

SQLMongoDBDescription
databasedatabase 
tablecollection表===集合
rowdocument行===文档
columnfield列===属性
indexindex 
table joins 是否支持关联查询
primary keyprimary keyMongoDB自动把id设置为主键

 

 

 

 

 

 

 

 


HTML5 语音     window.AudioContext    AudioNode    window.URL.createObjectURL(..)

function isMeidaEnable() {
    return !!(navigator.getUserMedia   
              ||navigator.webkitGetUserMedia
              ||navigator.mozGetUserMedia
              ||navigator.msGetUserMedia);
}
if (isMediaEnable()) {
    console.log('Enabled');
}

 

 

=================================================================

十二: HttpClient 正则表达式 

URL: new URL(..).openStream()

HttpClient: HttpClients.createDefault().execute(..)

/// 准备参数
List<NameValuePair> paramList = new ArrayList<>();
for (Map.Entry<String, String> entry : parameterMap.entrySet()) {
	paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
/// 设置参数到请求参数
UrlEncodedFormEntity paramEntity = new UrlEncodedFormEntity(paramList, Consts.UTF_8);
/// HttpGet HttpPost 相当于在地址栏输入URL
/// HttpGet httpGet = new HttpGet(EntityUtils.toString(paramEntity));
HttpPost httpPost = new HttpPost(“http://…”);
/// 设置超时等参数 此处采用默认配置
RequestConfig requestConfig = RequestConfig.DEFAULT;
httpPost.setConfig(requestConfig);
httpPost.setEntity(paramEntity);
/// HttpClient 相当于一个浏览器
CloseableHttpClient httpclient = HttpClients.createDefault();
/// 浏览器发送请求
CloseableHttpResponse response = httpclient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
	HttpEntity resultEntity = response.getEntity();
	String jsonText = EntityUtils.toString(resultEntity);
	// TODO jsonText 是请求返回的结果
	EntityUtils.consume(resultEntity); /// 确认是否还有内容并关闭
	response.close();
	httpclient.close();
}
else if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY
         || statusCode == HttpStatus.SC_MOVED_TEMPORARILY
         || statusCode == HttpStatus.SC_SEE_OTHER        
         || statusCode == HttpStatus.SC_TEMPORARY_REDIRECT ) {
	/// 重定向地址头部
	Header header = httpPost.getFirstHeader(“location”);
	String redirectURL = header.getValue();
	// TODO 
}      

SSL/TLS HTTPS Hyper Text Transfer Protocol over Secure Socket Layer

与 非 SSL/TLS 主要区别在于 HttpClient 的获取

public HttpClient sslHttpClient() throws Exception {
	SSLContext context = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
		@Override
		public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            /// 忽略验证直接通过
			return true;
		}
	}).build();
	SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(context);
	return HttpClients.custom().setSSLSocketFactory(factory).build();
}

正则表达式处理文本

public void analysis(String html) {
	Pattern p = Pattern.compile("<tr>.*?</tr>");
	Matcher m = p.matcher(html);
	while (m.find()) {
		String item = m.group();
		// TODO item 是匹配的字符
	}
}

HtmlParser Jsoup 解析HTML文档

Gson 处理 JSON 文本

 

 

=================================================================

十三: Android仿QQ UDP协议通信 Adapter设计模式

android.app.Activity

android.app.Service

android.view.View

android.content.BroadcastReceiver

android.content.ContentProvider


Activity 之间对象传递 需要使用 Serializable / Parcelable 

Parcelable 是 Android 提供的轻量级高效内存序列化机制 

Android Studio 可以安装 Parcelable 插件自动生成相应代码


设计模式之 Adapter   ArrayAdapter, BaseAdapter

Adapter数据视图转换逻辑


AndroidManifest.xml  [ˈmænɪfest]   Android全局配置文件,位于项目根目录,自行查阅

Android应用分为四个层次:

Linux内核层: 管理CPU、RAM以及为硬件提供驱动支持

系统运行层: 系统核心运行库和Android虚拟机

应用程序框架: Android SDK 面向APP程序设计者、开发者

用户应用程序: 发行的各类APP,QQ、Wechat等


Java 虚拟机把 .java 编译为 .class 

而 Android 虚拟机 在此基础上继续,把 各个分散的 .class 压缩到同一个文件中(自行查阅)

再被编译为能被 Dalvik ART 执行的 dex 文件

最后一步都相同,转换为命令交由操作系统运行

 

 

=================================================================

十四: Android新闻客户端 OkHttp/Volley请求框架  Glide图片加载 

LBS: Location Based Service

Volley.newRequestQueue(..).add(new ***Request(..)) 执行HTTP请求

<uses-permission android:name="android.permission.INTERNET" />

Fragment  Activity 

FragmentTransaction ft = getSupportFragmentManger().beginTransaction();


class **Adapter extends BaseAdapter {

    public View getView(int position, View view, ViewGroup parent) {

        if (view == null) {     /// 加入判断,可以复用,不用浪费资源再创建

           view = LayoutInflater.from(context).inflate(view_id)

        }

        view.findViewById(id_id);

    }

}


URL 发送 HTTP 请求

URL url = new URL(...);
HttpUrlConnection con = (HttpUrlConnection) url.openConnection();
BufferedReader reader = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
StringBuilder buf = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
    buf.append(buf + "\n");
}
reader.close();

 

 

=================================================================

十五: XMPP Openfire Smack Android实时通信APP

XMPP: Extensible Messaging and Presence Protocol

Smack: 客户端类库

Openfire: 基于XMPP协议,采用Java语言开发的实时协作服务器 下载

 

build.gradle 引入 smack 库

compile 'org.igniterealtime.smack:smack-android-extensions:4.1.9'

compile 'org.igniterealtime.smack:smack-tcp:4.1.9'

 

AsyncTask

onPreExecute()  UI主线程调用,显示进度等UI

doInBackground()  后台异步线程执行

onPostExecute()   UI主线程调用,更新UI

getStatus()

calcel()   异步线程取消执行销毁


EventBus  

@Subscribe(ThreadMode = ThreadMode.MAIN) 订阅消息

implements StanzaListener/ChatMessageListener


集成百度定位API

 

标签:return,String,读书笔记,Java,微课,new,byte,null,public
来源: https://blog.csdn.net/u011225581/article/details/112384717