Android笔记----Android的网络应用

基于TCP协议的网络通信

使用URL访问网络资源

使用HTTP访问网络

使用WebView视图显示网页

 

 

 

基于TCP协议的网络通信

TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket,通信的两端之间形成网络虚拟链路。Java对基于TCP协议的网络通信提供了良好的封装,Java使用Socket对象来代表两端的通信接口,并通过Socket产生IO流来进行网络通信。

1.1 使用ServerSocket创建TCP服务器端

Java中能接收其他通信实体连接请求的类是ServerSocket, ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。 ServerSocket包含一个监听来自客户端连接请求的方法。

Socket accept():如果接收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket;否则该方法将一直处于等待状态,线程也被阻塞。

为了创建ServerSocket对象,ServerSocket类提供了如下几个构造器:

ServerSocket(int port):用指定的端口port来创建一个ServerSocket。该端口应该是有一个有效的端口整数值:0~65535。

ServerSocket(int port,int backlog):增加一个用来改变连接队列长度的参数backlog。

ServerSocket(int port,int backlog,InetAddress localAddr):在机器存在多个 IP地址的情况下,允许通过localAddr这个参数来指定将ServerSocket绑定到指定的IP地址。

当ServerSocket使用完毕,应使用ServerSocket的close()方法来关闭该ServerSocket。

通常情况下,服务器不应该只接受一个客户端请求,而应该不断地接受来自客户端的所有请求,所以Java程序通常会通过循环,不断地调用ServerSocket的accept()方法。如下代码片段所示:

1.2 使用Socket进行通信

客户端通常可使用Socket的构造器来连接到指定服务器,Socket通常可使用如下两个构造器:

Socket(InetAddress/String remoteAddress, int port):创建连接到指定远程主机、远程端口的Socket。

Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, int localPort):创建连接到指定远程主机、远程端口的Socket,并指定本地IP地址和本地端口号。

上面两个构造器中指定远程主机时既可使用InetAddress来指定,也可直接使用String对象来指定,但程序通常使用String对象(如127.0.0.1)来指定远程IP。

以上代码将会连接到指定服务器,让服务器端的ServerSocket的accept()方法向下执行。

当客户端、服务器端产生了对应的Socket之后,程序无须再区分服务器、客户端,而是通过各自的Socket进行通信,Socket提供如下两个方法来获取输入流和输出流:

InputStream getInputStream():返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据。

OutputStream getOutputStream():返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据。

例:简单网络通信:

服务器端程序代码:

SimpleServer.java

public class SimpleServer
{
	public static void main(String[] args)
		throws IOException
	{
		//创建一个ServerSocket,用于监听客户端Socket的连接请求
		ServerSocket ss = new ServerSocket(30000);
		//采用循环不断接受来自客户端的请求
		while (true)
		{
			//每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
			Socket s = ss.accept();
			OutputStream os = s.getOutputStream();
			os.write("您好,您收到了服务器的新年祝福!\n"
				.getBytes("utf-8"));
			//关闭输出流,关闭Socket
			os.close();
			s.close();
		}
	}
}

客户端程序:

SimpleClient.java

public class SimpleClient extends Activity
{
	EditText show;
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		show = (EditText) findViewById(R.id.show);
		//关闭输入流、socket
		try
		{
			Socket socket = new Socket("127.0.0.1" , 30000);
			//将Socket对应的输入流包装成BufferedReader
			BufferedReader br = new BufferedReader(
				new InputStreamReader(socket.getInputStream()));
			//进行普通IO操作
			String line = br.readLine();
			show.setText("来自服务器的数据:" + line);
			br.close();
			socket.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}
<!--  授权访问互联网-->
	<uses-permission android:name="android.permission.INTERNET"/>

总结Socket通信,创建服务器步骤:

指定端口实例化一个ServerSocket

调用ServerSocket的accept()等待连接

获取位于该底层Socket的流以进行读写操作

对数据封装成流

对Socket进行读写

关闭打开的流

总结Socket通信,创建客户端的步骤:

通过IP地址和端口实例化Socket,请求连接服务器

获取Socket上的流以进行读写

把流包装进BufferedReader/PrintWriter的实例

对Socket进行读写

关闭打开的流

1.3  多线程

实际应用中的客户端则可能需要和服务器端保持长时间通信,即服务器需要不断地读取客户端数据,并向客户端写入数据;客户端也需要不断地读取服务器数据,并向服务器写入数据。

服务器应该为每个Socket单独启动一条线程,每条线程负责与一个客户端进行通信。

客户端读取服务器数据的线程同样会被阻塞,所以系统应该单独启动一条线程,该线程专门负责读取服务器数据。

例:C/S聊天室程序:

服务端程序:

MyServer.java

public class MyServer
{
	//定义保存所有Socket的ArrayList
	public static ArrayList<Socket> socketList
		= new ArrayList<Socket>();
    public static void main(String[] args)
		throws IOException
    {
        ServerSocket ss = new ServerSocket(30000);
		while(true)
		{
			//此行代码会阻塞,将一直等待别人的连接
			Socket s = ss.accept();
			socketList.add(s);
			//每当客户端连接后启动一条ServerThread线程为该客户端服务
			new Thread(new ServerThread(s)).start();
		}
    }
}

ServerThread.java

//负责处理每个线程通信的线程类
public class ServerThread implements Runnable
{
	//定义当前线程所处理的Socket
	Socket s = null;
	//该线程所处理的Socket所对应的输入流
	BufferedReader br = null;
	public ServerThread(Socket s)
		throws IOException
	{
		this.s = s;
		//初始化该Socket对应的输入流
		br = new BufferedReader(new InputStreamReader(
			s.getInputStream() , "utf-8"));   //②
	}
	public void run()
	{
		try
		{
			String content = null;
			//采用循环不断从Socket中读取客户端发送过来的数据
			while ((content = readFromClient()) != null)
			{
				//遍历socketList中的每个Socket,
				//将读到的内容向每个Socket发送一次
				for (Socket s : MyServer.socketList)
				{
					OutputStream os = s.getOutputStream();
					os.write((content + "\n").getBytes("utf-8"));
				}
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	//定义读取客户端数据的方法
	private String readFromClient()
	{
		try
		{
			return br.readLine();
		}
		//如果捕捉到异常,表明该Socket对应的客户端已经关闭
		catch (IOException e)
		{
			//删除该Socket。
			MyServer.socketList.remove(s);    //①
		}
		return null;
	}
}

客户端程序:

MultiThreadClient.java

public class MultiThreadClient extends Activity
{
	// 定义界面上的两个文本框
	EditText input, show;
	// 定义界面上的一个按钮
	Button send;
	OutputStream os;
	Handler handler;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		input = (EditText) findViewById(R.id.input);
		send = (Button) findViewById(R.id.send);
		show = (EditText) findViewById(R.id.show);
		Socket s;
		handler = new Handler()
		{
			@Override
			public void handleMessage(Message msg)
			{
				// 如果消息来自于子线程
				if (msg.what == 0x123)
				{
					// 将读取的内容追加显示在文本框中
					show.append("\n" + msg.obj.toString());
				}
			}
		};
		try
		{
			s = new Socket("127.0.0.1", 30000);
			// 客户端启动ClientThread线程不断读取来自服务器的数据
			new Thread(new ClientThread(s, handler)).start(); // ①
			os = s.getOutputStream();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		send.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				try
				{
					// 将用户在文本框内输入的内容写入网络
					os.write((input.getText().toString() + "\r\n")
						.getBytes("utf-8"));
					// 清空input文本框
					input.setText("");
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		});
	}
}

客户端线程:

ClientThread.java

public class ClientThread implements Runnable
{
	//该线程负责处理的Socket
	private Socket s;
	private Handler handler;
	//该线程所处理的Socket所对应的输入流
	BufferedReader br = null;
	public ClientThread(Socket s , Handler handler)
		throws IOException
	{
		this.s = s;
		this.handler = handler;
		br = new BufferedReader(
			new InputStreamReader(s.getInputStream()));
	}
	public void run()
	{
		try
		{
			String content = null;
			//不断读取Socket输入流中的内容。
			while ((content = br.readLine()) != null)
			{
				// 每当读到来自服务器的数据之后,发送消息通知程序界面显示该数据
				Message msg = new Message();
				msg.what = 0x123;
				msg.obj = content;
				handler.sendMessage(msg);
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}

使用URL访问网络资源

URL对象代表统一资源定位器,它是指向互联网”资源”的指针,资源可以是简单的文件或目录,也可以是对更复杂的对象的引用,URL可由协议名、主机、端口和资源组成 。

URL类提供了多个构造器用于创建URL对象,一旦获得了URL对象之后,可以调用如下常用方法来访问该URL对应的资源。

String getFile():获取此URL的资源名

String getHost():获取此URL的主机名

String getPath():获取些URL的路径部分

int getPort():获取此URL的端口号

String getProtocol():获取此URL的协议名称

String getQuery():获取此URL的查询字符串部分

URLConnection openConnection():URL所引用远程对象连接

InputStream openStream():打开与些URL的连接,并返回一个用于读取该URL资源的InputStream。

例:使用URL读取网络资源:

URLTest.java

public class URLTest extends Activity
{
	ImageView show;
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		show = (ImageView) findViewById(R.id.show);
		// 定义一个URL对象
		try
		{
			URL url = new URL("http://www.xxx.com/photo.png");
			// 打开该URL对应的资源的输入流
			InputStream is = url.openStream();
			// 从InputStream中解析出图片
			Bitmap bitmap = BitmapFactory.decodeStream(is);
			// 使用ImageView显示该图片
			show.setImageBitmap(bitmap);
			is.close();
			// 再次打开URL对应的资源的输入流
			is = url.openStream();
			// 打开手机文件对应的输出流
			OutputStream os = openFileOutput("crazyit.png"
				, MODE_WORLD_READABLE);
			byte[] buff = new byte[1024];
			int hasRead = 0;
			// 将URL对应的资源下载到本地
			while((hasRead = is.read(buff)) > 0)
			{
				os.write(buff, 0 , hasRead);
			}
			is.close();
			os.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}

2.1 使用URLConnection提交请求

通常创建一个和URL的连接,并发送请求。读取此URL引用的资源需要如下几个步骤 :

通过调用Url对象openConnection()方法创建URLConnection对象。

设置URLConnection的参数和普通请求属性。

如果只是发送get方式请求,使用Connect方法建立和远程资源之间的实际连接即可;如果需要发送post方式的请求需要获取URlConnection实例对应的输出流来发送请求参数。

远程资源变为可用,程序可以访问远程资源的头字段或通过输入流读取远程资源的数据。

在建立和远程资源的实际连接之前,可以通过如下方法来设置请求头字段。

setAllowUserInteraction:设置该URLConnection的allowUserInteraction请求头字段的值。

setDoInput:设置该URLConnection的doInput请求头字段的值。

setDoOutput:设置该URLConnection的doOutput请求头字段的值。

setIfModifiedSince:设置该URLConnection的ifModifiedSince请求头字段的值。

setUseCaches:设置该URLConnection的useCaches请求头字段的值

还可以使用如下方法来设置或增加通用头字段。

setRequestProperty(String key,String value):设置该URLConnection的key请求头字段的值为value。

addRequestProperty(String key,String value):为该URLConnection的key请求头字段增加value值。

当远程资源可用时,程序可以使用以下方法用于访问头字段和内容。

Object getContent():获取该URLConnection的内容

String getHeaderField(String name):获取指定响应头字段的值

getInputStream():返回该URLConnection对应的输入流,用于获取URLConnection响应的内容。

getOutputStream():返回该URLConnection对应的输出流,用于向URLConnection发送请求参数。

例:向Web站点发送GET、POST请求:

GetPostMain.java

public class GetPostMain extends Activity
{
	Button get , post;
	EditText show;
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		get = (Button) findViewById(R.id.get);
		post = (Button) findViewById(R.id.post);
		show = (EditText)findViewById(R.id.show);
		get.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				String response = GetPostUtil
					.sendGet("http://127.0.0.1:8080/abc/a.jsp" , null);
				show.setText(response);

			}
		});
		post.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				String response = GetPostUtil
					.sendPost("http://127.0.0.1:8080/abc/login.jsp"
					, "name=xxx&pass=123");
				show.setText(response);

			}
		});
	}
}

GetPostUtil.java

public class GetPostUtil
{
	/**
	 * 向指定URL发送GET方法的请求
	 *
	 * @param url
	 *            发送请求的URL
	 * @param params
	 *            请求参数,请求参数应该是name1=value1&name2=value2的形式。
	 * @return URL所代表远程资源的响应
	 */
	public static String sendGet(String url, String params)
	{
		String result = "";
		BufferedReader in = null;
		try
		{
			String urlName = url + "?" + params;
			URL realUrl = new URL(urlName);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent",
				"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
			// 建立实际的连接
			conn.connect();
			// 获取所有响应头字段
			Map<String, List<String>> map = conn.getHeaderFields();
			// 遍历所有的响应头字段
			for (String key : map.keySet())
			{
				System.out.println(key + "--->" + map.get(key));
			}
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(
				new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null)
			{
				result += "\n" + line;
			}
		}
		catch (Exception e)
		{
			System.out.println("发送GET请求出现异常!" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输入流
		finally
		{
			try
			{
				if (in != null)
				{
					in.close();
				}
			}
			catch (IOException ex)
			{
				ex.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 向指定URL发送POST方法的请求
	 *
	 * @param url
	 *            发送请求的URL
	 * @param params
	 *            请求参数,请求参数应该是name1=value1&name2=value2的形式。
	 * @return URL所代表远程资源的响应
	 */
	public static String sendPost(String url, String params)
	{
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try
		{
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent",
				"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(params);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(
				new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null)
			{
				result += "\n" + line;
			}
		}
		catch (Exception e)
		{
			System.out.println("发送POST请求出现异常!" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally
		{
			try
			{
				if (out != null)
				{
					out.close();
				}
				if (in != null)
				{
					in.close();
				}
			}
			catch (IOException ex)
			{
				ex.printStackTrace();
			}
		}
		return result;
	}
}

使用HTTP访问网络

3.1 使用HttpURLConnection

URLConnection还有一个子类:HttpURLConnection,可以用于向指定网站发送GET请求、POST请求。它在URLConnection的基础上提供了如下方法:

int getResponseCode():获取服务器的响应代码

String getResponseMessage():获取服务器的响应信息

String getRequestMethod():获取发送请求的方法

Void setRequestMethod(String method):设置发送请求的方法

例:多线程下载:

为了实现多线程,程序可按如下步骤进行:

创建URL对象

获取指定URL对象所指象的资源大小(由getContentLength()方法实现),此处用到了HttpURLConnection类。

在本地磁盘上创建一个与网络资源相同大小的空文件

计算每条线程应该下载网络资源的哪个部分

依次创建、启动多条线程来下载网络资源的指定部分。

3.2 使用Apache HttpClient

HttpClient是一个增强版的HttpURLConnection,它是一个简单的客户端(并不是浏览器),可以发送HTTP请求,接收HTTP响应,以及管理HTTP连接。但不会缓存服务器的响应,不能执行HTML页面中嵌入的JavaScript代码,也不会对页面内容进行任何解析、处理。

Android已经成功地集成了HttpClient,可以直接在Android应用中使用HttpClient来访问提交请求、接收响应。使用HttpClient的步骤如下:

创建HttpClient对象

如果需要发送GET请求,创建HttpGet对象,如果需要发送POST请求,创建HttpPost对象。

如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数。

调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

调用HttpResponse的getAllHeader()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包含了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

例:HttpClient访问被保护的资源:

HttpClientTest.java

public class HttpClientTest extends Activity
{
	Button get;
	Button login;
	EditText response;
	HttpClient httpClient;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// 创建DefaultHttpClient对象
		httpClient = new DefaultHttpClient();
		get = (Button) findViewById(R.id.get);
		login = (Button) findViewById(R.id.login);
		response = (EditText) findViewById(R.id.response);
		get.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				// 创建一个HttpGet对象
				HttpGet get = new HttpGet(
					"http://127.0.0.1:8080/foo/secret.jsp");
				try
				{
					// 发送GET请求
					HttpResponse httpResponse = httpClient.execute(get);
					HttpEntity entity = httpResponse.getEntity();
					if (entity != null)
					{
						// 读取服务器响应
						BufferedReader br = new BufferedReader(
							new InputStreamReader(entity.getContent()));
						String line = null;
						response.setText("");
						while ((line = br.readLine()) != null)
						{
							// 使用response文本框显示服务器响应
							response.append(line + "\n");
						}
					}
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		});
		login.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				final View loginDialog = getLayoutInflater().inflate(
					R.layout.login, null);
				new AlertDialog.Builder(HttpClientTest.this)
					.setTitle("登录系统")
					.setView(loginDialog)
					.setPositiveButton("登录",
						new DialogInterface.OnClickListener()
						{
							@Override
							public void onClick(DialogInterface dialog,
								int which)
							{
								String name = ((EditText) loginDialog
									.findViewById(R.id.name)).getText()
									.toString();
								String pass = ((EditText) loginDialog
									.findViewById(R.id.pass)).getText()
									.toString();
								HttpPost post = new HttpPost(
									"http://127.0.0.1:8080/foo/login.jsp");
								// 如果传递参数个数比较多的话可以对传递的参数进行封装
								List<NameValuePair> params = new ArrayList<NameValuePair>();
								params
									.add(new BasicNameValuePair("name", name));
								params
									.add(new BasicNameValuePair("pass", pass));
								try
								{
									// 设置请求参数
									post.setEntity(new UrlEncodedFormEntity(
										params, HTTP.UTF_8));
									// 发送POST请求
									HttpResponse response = httpClient
										.execute(post);
									// 如果服务器成功地返回响应
									if (response.getStatusLine()
										.getStatusCode() == 200)
									{
										String msg = EntityUtils
											.toString(response.getEntity());
										// 提示登录成功
										Toast.makeText(HttpClientTest.this,
											msg, 5000).show();
									}
								}
								catch (Exception e)
								{
									e.printStackTrace();
								}
							}
						}).setNegativeButton("取消", null).show();
			}
		});
	}
}

使用WebView视图显示网页

4.1 使用WebView浏览网页

WebView的用法与普通的ImageView组件的用法基本相似,它提供了大量方法来执行浏览器操作,例如如下常用方法。

void goBack():后退

void goForward():前进

void loadUrl(String url):加载指定的URL对应的网页

boolean zoomIn():放大网页

boolean zoomOut():缩小网页

例:迷你浏览器:

MiniBrowser.java

public class MiniBrowser extends Activity
{
	EditText url;
	WebView show;
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// 获取页面中文本框、WebView组件
		url = (EditText) findViewById(R.id.url);
		show = (WebView) findViewById(R.id.show);
	}
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		if (keyCode == KeyEvent.KEYCODE_SEARCH)
		{
			String urlStr = url.getText().toString();
			// 加载、并显示urlStr对应的网页
			show.loadUrl(urlStr);
			return true;
		}
		return false;
	}
}

Main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/url"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <!-- 显示页面的WebView组件 -->

    <WebView
        android:id="@+id/show"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

4.2 使用WebView加载HTML代码

利用WebView可以对HTML字符串进行解析、当成HTML页面来显示。 WebView提供了一个loadDataWithBaseURL(String baseUrl,String data,String mimeType,String encoding,String historyUrl)方法,该方法是对loadData(String data, data,String mimeType,String encoding)方法的增强,它不会产生乱码。

例:使用WebView加载HTML:

在配置文件中加上访问网络的权限

ViewHtml.java

public class ViewHtml extends Activity
{
	WebView show;
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// 获取程序中的WebView组件
		show = (WebView) findViewById(R.id.show);
		StringBuilder sb = new StringBuilder();
		// 拼接一段HTML代码
		sb.append("<html>");
		sb.append("<head>");
		sb.append("<title> 欢迎您 </title>");
		sb.append("</head>");
		sb.append("<body>");
		sb.append("<h2> 欢迎您访问<a href=\"http://http://blog.csdn.net\">"
			+ "CSDN</a></h2>");
		sb.append("</body>");
		sb.append("</html>");
		// 使用简单的loadData方法会导致乱码,可能是Android API的Bug
		//show.loadData(sb.toString() , "text/html" , "utf-8");
		// 加载、并显示HTML代码
		show.loadDataWithBaseURL(null, sb.toString()
			, "text/html" , "utf-8", null);
	}
}
时间: 2024-10-12 08:34:09

Android笔记----Android的网络应用的相关文章

Android笔记——Android中数据的存储方式(二)

我们在实际开发中,有的时候需要储存或者备份比较复杂的数据.这些数据的特点是,内容多.结构大,比如短信备份等.我们知道SharedPreferences和Files(文本文件)储存这种数据会非常的没有效率.如果学过JavaWeb的朋友,首先可能想到的是数据库.当然了数据库是一个方案,那么是否还有其他的解决方案呢?今天我们在讲下Android笔记——Android中数据的存储方式(一) 提到的除了SharedPreferences和Files(文本文件)以外的其他几种数据储存方式:xml文件.SQL

转载:android笔记--android中的多线程--Handler, Looper, MessageQueue, Message类

什么时候使用多线程: 1. 耗时操作使用多线程, 耗时操作放在UI线程中会导致用户的操作无法得到响应. 2. 阻塞操作使用多线程, 理由同上. 3. 多核CUP的设备使用多线程, 可以有效提高CPU的利用率. 4. 并行操作使用多线程. android中的多线程模型主要涉及的类有:Looper, Handler, MessageQueue, Message等. 一:Looper类: 1 static final ThreadLocal<Looper> sThreadLocal = new Th

Android笔记——Android中数据的存储方式(三)

Android系统集成了一个轻量级的数据库:SQLite,所以Android对数据库的支持很好,每个应用都可以方便的使用它.SQLite作为一个嵌入式的数据库引擎,专门适用于资源有限的设备上适量数据存取,现在的主流移动设备像Android.iPhone等都使用SQLite作为复杂数据的存储引擎,并且它是以手机内存为储存的. 那么,实际开发项目中有大量数据需要读写,并且需要面临大量用户的并发储存的情况呢.就不应该把数据存放在手机等移动设备的SQLite数据库里,移动设备的储存能力和计算能力都不足以

android笔记——android studio环境搭建

前段时间开始了学习android的旅程,想要写一个随笔,记录一下学习android的点点滴滴!从现在起每周一和周六周日将在这里持续更新最近学习android的情况. 今天将在这里展示如何利用android studio 搭建android开发环境. 第一步:下载安装JDK8     www.oracle.com 配置系统环境变量 JAVA_HOME   C:\Program Files\Java\jdk1.8.0_66 CLASSPATH    .; C:\Program Files\Java\

Android笔记——Android自定义控件

目录: 1.自定义控件概述 01_什么是自定义控件 Android系统中,继承Android系统自带的View或者ViewGroup控件或者系统自带的控件,并在这基础上增加或者重新组合成我们想要的效果. 02_为什么用自定义控件 系统控件无法满足需求时,需要自定义控件. 系统的控件在不同手机长得不一样,我们希望在不同手机实现相同的效果: 有些手机上的控件长得不好看,希望好看一些. 系统控件的功能有限,需要在基础上增加功能. 03_怎么用自定义控件-三种方式 1.使用系统控件,重新组合,实现自定义

Android笔记----Android的数据存储和IO操作

使用SharedPreferences File存储 SQLite数据库           使用SharedPreferences 1.1 SharedPreferences与Editor简介 应用程序有少量的数据需要保存,而且这些数据的格式很简单,都是普通的字符串.标量类型的值等,比如应用程序的各种配置信息,对于这种数据,Android提供了SharedPreferences. SharedPreferences保存的数据主要是类似于配置信息格式的数据,因此它保存的数据主要是简单类型的key

Android笔记----Android传感器开发

Android的传感器开发 Android的常用传感器 传感器应用案例         Android的传感器开发 1.1 开发传感器应用 开发传感器的步骤如下: 调用Context的getSystemService(Context.SENSOR_SERVICE)方法获取SensorManager对象. 调用SensorManager的getDefaultSensor(int type)方法来获取指定类型的传感器. 一般在Activity的onResume()方法中调用SensorManager

Android笔记:Android应用的基本组件

Android应用程序由松耦合组件,并使用项目清单(Mainifest)绑定到一起.1.Activity和View    Activity是Android应用表现形式,应用程序中的每一个屏幕都是Activity类的扩展.Activity使用View在一个屏幕上形成显示信息和响应用户动作的图形界面,多个Activity之间可以进行相互跳转,在一些应用中,一个屏幕甚至会返回值给前一个屏幕.    VIew是Android中用户图形界面的基类,为用户提供了可视化的界面,View又可以分为VIew和Vi

Android笔记——Android中visibility属性VISIBLE、INVISIBLE、GONE的区别

在Android开发中,大部分控件都有visibility这个属性,其属性有3个分别为"visible "."invisible"."gone".主要用来设置控制控件的显示和隐藏.有些人可能会疑惑Invisible和gone是有什么区别的???那么,我们带着这个疑问看下面: 其在XML文件和Java代码中设置如下: 可见(visible) XML文件:android:visibility="visible" Java代码:vi