安卓第七天笔记--网络编程一
安卓第七天笔记--网络编程一
Android对网络的支持
Android完全支持JDK本身的TCP,UDP网络通信API,也可以使用ServerSocket,Socket来建立基于TCP/IP协议的网络通信,还可以使用DatagramSocket,Datagrampacket,MulticastSocket来建立 基于UDP的协议网络通信
同时支持JDK提供的URL,URLConnection等网络通信API.
Andoirdgip内置了Apache的HttpClient,这样可以非常方便的发送HTTP请求,并获取HTTP响应.
1.Socket实现
服务器
package com.itheima.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
/**
* ServerSocket 服务端
* @Decription TODO
* @author 刘楠
*
* @time2016-2-22下午4:54:59
*/
public class MyServer {
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
public static void main(String[] args) {
try {
//建立serversocket
ServerSocket serverSocket = new ServerSocket(25000);
//服务器一直在运行状态
while(true){
//开始监听
Socket socket = serverSocket.accept();
socketList.add(socket);
//启动新的线程
new ServerThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
线程类
*/
package com.itheima.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) throws IOException {
//初始化
this.socket = socket;
}
@Override
public void run() {
String ip = socket.getInetAddress().getHostAddress();
System.out.println("ip:"+ip);
BufferedReader br=null;
OutputStream out = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream(),
"UTF-8"));
out = socket.getOutputStream();
String content = null;
while((content=br.readLine())!=null){
System.out.println("来自客户端:"+content);
//手动加上换行 符,不然没客户端收不到
out.write((content+"\n").toUpperCase().getBytes("utf-8"));
System.out.println("服务发出去了:");
}
out.close();
br.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.itheima.mutithreadclient.MainActivity">
<!--接收用户输入的内容-->
<EditText
android:id="@+id/input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="请输入要发送的内容"/>
<Button
android:id="@+id/send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送"/>
<!--接收服务返回的内容-->
<TextView
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
子线程
/**
* 线程类
* Created by 刘楠 on 2016-02-22 17:51.
*/
public class ClientThread implements Runnable{
private static final String TAG = "ClientThread";
private Socket s;
// 定义向UI线程发送消息的Handler对象
private Handler handler;
// 定义接收UI线程的消息的Handler对象
public Handler revHandler;
// 该线程所处理的Socket所对应的输入流
BufferedReader br = null;
OutputStream os = null;
public ClientThread(Handler handler)
{
this.handler = handler;
}
public void run()
{
try
{
s = new Socket("192.168.1.103", 25000);
br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
os = s.getOutputStream();
// 启动一条子线程来读取服务器响应的数据
new Thread()
{
@Override
public void run()
{
String content = null;
// 不断读取Socket输入流中的内容
try
{
while ((content = br.readLine()) != null)
{
// 每当读到来自服务器的数据之后,发送消息通知程序
// 界面显示该数据
Message msg = new Message();
msg.what = 0x123;
msg.obj = content;
handler.sendMessage(msg);
Log.i(TAG,"服务返回"+content);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}.start();
// 为当前线程初始化Looper
Looper.prepare();
// 创建revHandler对象
revHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
// 接收到UI线程中用户输入的数据
if (msg.what == 0x345)
{
// 将用户在文本框内输入的内容写入网络
try
{
//手动加上换行符
os.write((msg.obj.toString() + "\r\n")
.getBytes("utf-8"));
Log.i(TAG, "输入的" + msg.obj.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
};
// 启动Looper
Looper.loop();
}
catch (SocketTimeoutException e1)
{
System.out.println("网络连接超时!!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Activity
/**
*
* 使用ServketSocket做服务通信
*
*
* @author 刘楠
*/
public class MainActivity extends AppCompatActivity {
private EditText input;
private TextView show;
private ClientThread clientThread;
private Button send;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
input = (EditText) findViewById(R.id.input);
show = (TextView) findViewById(R.id.show);
send = (Button) findViewById(R.id.send);
/**
* 接收到消息要就显示
*/
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==0x123){
show.append("\n"+msg.obj.toString());
}
}
};
//初始化子线程
clientThread = new ClientThread(handler);
//启动子线程
new Thread(clientThread).start();
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String str = input.getText().toString().trim();
Message msg=new Message();
msg.what=0x345;
msg.obj=str;
//把内容发给子线程
clientThread.revHandler.sendMessage(msg);
//清空文本框
input.setText("");
}
});
}
}
<!--添加网络权限-->
<uses-permission android:name="android.permission.INTERNET"/>
2.URL连接网络
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/et_url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="请输入URL图片地址"/>
<Button
android:onClick="display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显示图片地址"/>
<ImageView
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Activity
/**
* URL连接网络
* 获取URL地址
* 打开流,获取流的内容
*
*/
public class MainActivity extends AppCompatActivity {
/*
标识表示成功
*/
private static final int SUCCESS = 1;
//路径写死了 也可以获取的方式
private String path ="http://img2.imgtn.bdimg.com/it/u=4114593003,3380074209&fm=21&gp=0.jpg";
/*
图片
*/
Bitmap bitmap;
/*
显示图片
*/
ImageView show;
/*
输入的URL
*/
private EditText et_url;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_url = (EditText) findViewById(R.id.et_url);
show = (ImageView) findViewById(R.id.show);
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case SUCCESS:
show.setImageBitmap(bitmap);
break;
}
}
};
}
/**
* 获取输入的地址并显示图片
* @param v 当前对象
*/
public void display(View v){
String strPath = et_url.getText().toString().trim();
if(TextUtils.isEmpty(strPath)){
Toast.makeText(this,"输入的路径不能为空",Toast.LENGTH_SHORT).show();
return ;
}
new Thread(new Runnable() {
@Override
public void run() {
try {
//获取URL
URL url = new URL(path);
//打开流获取资源
InputStream in = url.openStream();
//使用BitmapFactory转换为Bitmap
bitmap = BitmapFactory.decodeStream(in);
//获取消息
Message msg = Message.obtain();
msg.what=SUCCESS;
msg.obj=bitmap;
handler.sendMessage(msg);
//关闭
// in.close();
//把文件保存到本地
in =url.openStream();
OutputStream out = openFileOutput("test.png",MODE_PRIVATE);
byte [] buf = new byte [1024];
int len=0;
while((len=in.read(buf))!=-1){
out.write(buf,0,len);
}
out.close();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
添加网络权限
<!--添加网络权限-->
<uses-permission android:name="android.permission.INTERNET"/>
3.URLConnection连接网络
使用URLConnection连接网络
*Get方式只要 获取请求地址把请求参数拼接在URL地址后面"?username="+user+"&password="+password
* openConnection
* 设置请求头信息
* connect()建立实际连接
* 获取输入流conn.getInputStream
* 读取输入流中的内容
*
* Post方式,
* 请求地址
* ,将参数单独拼接为一个字符串params="username="+user+"&password="+password
* openConnection
* 设置请求头信息
* connect()建立实际连接
* setDoOuput(true)
* setDoInput(true)
* 写出参数conn.getOutPutStream().write(params.getBytes());
* 获取输入流conn.getInputStream
* 读取输入流中的内容
服务器Servlet
View Code
3.1get请求与Post请求
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.itheima.urlconnection.MainActivity">
<EditText
android:id="@+id/et_user"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名"/>
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="请输入密码"/>
<Button
android:onClick="get"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="GET请求"/>
<Button
android:onClick="post"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="POST 请求"/>
<TextView
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Activity
View Code
添加网络权限
<!--添加网络权限-->
<uses-permission android:name="android.permission.INTERNET"/>
4.Http网络连接
和URLConnection非常类似只获取连接为HttpURULConnection
/**
* 使用HttpURLConnection连接网络
*Get方式只要 获取请求地址把请求参数拼接在URL地址后面"?username="+user+"&password="+password
* openConnection
* 设置请求方法setRequestMethod("GET")必须大写
*
* 获取输入流conn.getInputStream
* 读取输入流中的内容
*
* Post方式,
* 请求地址
* ,将参数单独拼接为一个字符串params="username="+user+"&password="+password
* openConnection
* 设置请求方法setRequestMethod("POST")必须大写
* setDoOuput(true)
* setDoInput(true)
* 写出参数conn.getOutPutStream().write(params.getBytes());
* 获取输入流conn.getInputStream
* 读取输入流中的内容
*
*
*/
View Code
5.使用ApacheHttpClient
View Code
6.WebView
goBack():后退
goForward():前进
loadUrl(String url):加载指定URL的网页
boolean zoomln():放大网页
zoomOut():缩小网页
布局
布局Activity
/**
* WebView小型浏览器
*
*/
public class MainActivity extends AppCompatActivity {
/*
接收输入的URL
*/
private EditText et_url;
/*
显示网页内容
*/
private WebView wv_show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_url = (EditText) findViewById(R.id.et_url);
wv_show = (WebView) findViewById(R.id.wv_show);
}
@Override
public boolean onKeyDown(int keyCode,KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_MENU){
String urlStr = et_url.getText().toString().trim();
//加载
wv_show.loadUrl(urlStr);
return true;
}
return false;
}
}
添加权限
<uses-permission android:name="android.permission.INTERNET"/>
7.使用WebHTML加载HTML代码
WebView提供了一具
loadData(String data,String mimeType ,String encoding)方法用于加载HTML,这个方法加载中文时会有乱码
还有一个
loadDataWithURL(String data,String mimeType ,String encoding,String historyUrl)方法是第一个方法的加强,
data:指定的HTML代码
mimeType:指定HTML代码的MIME类型,对象HTML代码可指定为text/html
encoding:指定HTML代码编码所有的字符集:UTF-8
布局中只有一个WebView
/**
* WebView显示HTML
*/
public class MainActivity extends AppCompatActivity {
private WebView webView_show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取webView组件
webView_show = (WebView) findViewById(R.id.webView_show);
StringBuilder sb = new StringBuilder();
sb.append("<html>");
sb.append("<head>");
sb.append("<title> 欢迎WebView显示HTML</title>");
sb.append("</head>");
sb.append("<body>");
sb.append("<h1 align='center' style='color:red'>显示中文标题</h1>");
sb.append("</body>");
sb.append("</html>");
//加载并显示HTML这个中文会显示乱码
//webView_show.loadData(sb.toString(),"text/html","utf-8");
webView_show.loadDataWithBaseURL(null,sb.toString(),"text/html","utf-8",null);
}
}
9.WebView使用JavaScript调用Android
- 步骤:
- 1.调用WebView的get getSettings方法获取WebSettings
- 2.启用JAVAScript调用功能
- webSettings.setJavaScriptEnable(true)
- 3.调用webView的addJavaScript(Object obj,String name)方法
- 4.在javaScript脚本中通过刚才暴露的name对象调用Android
- 5.对象的方法上必须加上注解
-
/**
-
* 这具注解只能用在方法
-
*/
- @JavascriptInterface
-
*/
-
* 这具注解只能用在方法
Html在assets目录下
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>JS 调用</title>
</head>
<body>
<!-- 注意此处的myObj是Android暴露出来的对象 -->
<input type="button" value="弹Toast"
onclick="person.show();"/>
<input type="button" value="图书列表"
onclick="person.showList();"/>
</body>
</html>
布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
JAVABean:
/**
* Created by 刘楠 on 2016-02-23 09:00.
*/
public class Person {
private String name;
private int age;
private Context mContext;
public Person(Context context){
this.mContext = context;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@JavascriptInterface
public void show(){
Toast.makeText(mContext,"姓名"+this.name+",年龄:"+age,Toast.LENGTH_SHORT).show();
}
/**
* 这具注解只能用在方法
*/
@JavascriptInterface
public void showList(){
new AlertDialog.Builder(mContext)
//设置标题
.setTitle("人员列表")
.setIcon(R.mipmap.ic_launcher)
.setItems(new String [] {"JAVA","Android","C++","C","PYTHON"},null)
.setPositiveButton("确定",null)
.setNegativeButton("取消",null)
.create().show();
}
}
Activity
/**
* WebView使用JavaScript
*
*/
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView);
webView.loadUrl("file:///android_asset/test.html");
//获取WebView设置对象
WebSettings webSettings = webView.getSettings();
//启用javaScript
webSettings.setJavaScriptEnabled(true);
Person person = new Person(this);
person.setName("张三");
person.setAge(18);
//传递对象
webView.addJavascriptInterface(person, "person");
}
}