第十三章:Android中的互联网应用

一、通过Socket、ServerSocket进行网络编程

Socket、ServerSocket编程方式可以说是比较底层的网络编程方式,其他的高级协议(如HTTP)都是建立在此基础之上的,而且Socket编程是跨平台的编程,可以在异构语言之间进行通信,所以掌握Socket网络编程是掌握其他网络编程方式的基础。

1、Socket、ServerSocket编程模型

在Socket编程模式中,Socket类用来建立客户端程序,ServerSocket类用来建立服务器端程序。首先,要有服务器端程序。通过ServerSocket建立服务器端程序,一般指定一个监听端口,用来等待客户端的连接。客户端Socket要指定服务器端的IP地址和端口号。一旦连接建立,ServerSocket就可以获得一个Socket实例,通过Socket打开输入、输出流进行通信。

2、Socket编程实例

一般Socket在Android中的编程应用中,Android都作为客户端,因为无线上网IP地址的分配是由移动运营公司动态分配的,没有固定IP所以不能作为服务器端来使用。下面的实例是通过Android建立Socket客户端连接ServerSocket服务器端实现简单的通信。

/**
 * Socket服务器,响应Android客户端连接
 */
public class MyServer {
	public static void main(String[] args) {
		try {
			//实例化服务器套接字
			ServerSocket server = new ServerSocket(8888);
			//永真循环
			while(true){
				//获得客户端套接字
				Socket client = server.accept();
				//获得输出流
				OutputStream out = client.getOutputStream();
				//输出字符串
				String msg = "Hello Android!";
				//写字符串
				out.write(msg.getBytes());
				//关闭输出流
				client.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

socket.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/msgTextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="等待接受服务器消息..." />

</LinearLayout>
/**
 * 客户端接受服务器消息
 */
public class MainActivity extends Activity {
	private TextView MyText;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.socket);
        MyText = (TextView) findViewById(R.id.msgTextView01);
        try {
			Socket socket = new Socket("192.168.1.101",8888);
			InputStream in = socket.getInputStream();
			byte[] buffer = new byte[in.available()];
			in.read(buffer);
			String msg = new String(buffer);
			MyText.setText(msg);
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
}

二、通过URL进行网络编程

下面我们可以使用URL、URLConnection和HttpURLConnection进行URL网络连接,下面的实例要展示的是同URL连接、读取服务器的一张图片,并使用ImageView组件显示出来。

test_url.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/ImageView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
public class MainActivity extends Activity {
	private ImageView imageView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.test_url);
		imageView = (ImageView) findViewById(R.id.ImageView01);
		//要显示的图标路径
		String urlStr = "http://localhost:8080/tomcat.gif";
		try {
			//实例化URL
			URL url = new URL(urlStr);
			//1、直接使用URL获得输入流
			//InputStream in = url.openStream();
			
			//2、获得URLConnection
			URLConnection conn = url.openConnection();
			InputStream in = conn.getInputStream();
			
			//3、如果是HTTP协议可以使用HttpURLConnection
//			HttpURLConnection httpConn = (HttpsURLConnection)conn;
//			in = httpConn.getInputStream();
			//通过BitmapFactory获得Bitmap实例
			Bitmap bm = BitmapFactory.decodeStream(in);
			//为ImageView设置图片
			imageView.setImageBitmap(bm);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

三、通过HTTP进行网络编程

在Android中针对HTTP进行网络通信有两种:一是HttpURLConnection;二是ApacheHTTP客户端。

1、使用HttpURLConnection

如果我们知道访问资源的URL,并且是基于HTTP的,那么我们就可以使用HttpURLConnection进行请求/响应。

下面通过一个用户登录实例,来比较学习使用HttpURLConnection和使用ApacheHTTP客户端的异同

http1.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TableLayout 
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:stretchColumns="1">
        <TableRow>
            <TextView 
                android:text="用户名称:"
	       android:layout_width="wrap_content"
	       android:layout_height="wrap_content" />
            <EditText 
                android:id="@+id/usernameEditText"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        </TableRow>
        <TableRow>
            <TextView 
                android:text="用户密码:"
	       android:layout_width="wrap_content"
	       android:layout_height="wrap_content" />
            <EditText 
                android:id="@+id/passwordEditText"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        </TableRow>
        <TableRow android:gravity="right">
            <Button 
                android:text="取消"
                android:id="@+id/cancelButton"
	       android:layout_width="wrap_content"
	       android:layout_height="wrap_content" />
            <Button 
                android:text="登录"
                android:id="@+id/loginButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </TableRow>
    </TableLayout>
</LinearLayout>

LoginServlet

public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		response.setContentType("text/html");
		((ServletRequest) response).setCharacterEncoding("utf-8");
		PrintWriter out = response.getWriter();
		String msg = null;
		if(username != null && username.equals("admin") && password != null && password.equals("1")){
			msg = "登录成功";
		}else{
			msg = "登录失败";
		}
		out.print(msg);
		out.flush();
		out.close();		
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}
}

Activity

public class MainActivity extends Activity {
	private Button cancelBtn,loginBtn;
	private EditText userEditText,pwdEditText;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.http1);
		cancelBtn = (Button) findViewById(R.id.cancelButton);
		loginBtn = (Button) findViewById(R.id.loginButton);
		userEditText = (EditText) findViewById(R.id.usernameEditText);
		pwdEditText = (EditText) findViewById(R.id.passwordEditText);
		//设置登录监听器
		loginBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				String username = userEditText.getText().toString();
				String password = pwdEditText.getText().toString();
				login(username, password);
			}
		});
		cancelBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				finish();
			}
		});
	}
	//定义一个显示提示信息的对话框
	private void showDialog(String msg){
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(msg)
		       .setCancelable(false)
		       .setPositiveButton("确定",new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int id) {
						
					}
		       });
		AlertDialog alert = builder.create();
		alert.show();
	}
	//通过用户和密码进行查询,发送Post请求,获得响应结果
	private void login(String username,String password){
		//请求URL
		String urlStr = "访问LoginServlet的路径+?";//Servlet
		//查询字符串
		String queryString = "username=" + username + "&password=" + password;
		urlStr += queryString;
		try {
			//实例化URL
			URL url = new URL(urlStr);
			//获得HttpURLConnection实例
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			//如果请求成功
			if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){
				//获得输入流
				InputStream in = conn.getInputStream();
				//数组缓存
				byte[] b = new byte[in.available()];
				//读数据到缓存
				in.read(b);
				//转换为字符串
				String msg = new String(b);
				//显示对话框
				showDialog(msg);
				//关闭输入流
				in.close();
			}
			//断开连接
			conn.disconnect();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 使用Apache HTTP客户端
	 * 只是把login方法改写成了Apache HTTP Client,其他的都没有变化
	 * 改写后的方法如下login2
	 */
	private void login2(String username,String password){
		String urlStr = "....../LoginServlet";
		HttpPost request = new HttpPost(urlStr);
		//如果传递参数个数比较多的话,我们可以对传递的参数进行封装
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("username", username));
		params.add(new BasicNameValuePair("password", password));
		try {
			//设置请求参数项
			request.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
			//执行请求返回响应
			HttpResponse response = new DefaultHttpClient().execute(request);
			//判断是否请求成功
			if(response.getStatusLine().getStatusCode() == 200){
				//获得响应消息
				String msg = EntityUtils.toString(response.getEntity());
				showDialog(msg);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

2、使用ApacheHTTP客户端

HTTP是一种请求/响应机制,在Servlet编程中我们会使用HttpServletRequest和HttpServletResponse表示请求和响应,ApacheHTTP客户端也对请求和响应进行封装,根据请求方法的不同,我们会用到HttpGet和HttpPost两个对象,响应对象是HttpResponse,使用DefaultHttpClient执行请求获得响应。

本实例在上面的实例基础上只是把login方法改写成使用Apache HTTP Client,其他都没有变化。代码详见上实例中的Activity的login2()方法。

四、通过Web Service进行网络编程

Web Service是实现异构程序之间方法调用的一种机制。Web Service通过一种XML格式的特殊文件来描述方法、参数、调用和返回值,这样格式的XML文件被称为WEDL(Web Service Description Language),即Web服务描述语言。Web Service采用的通信协议是SOAP(Simple Object Access Protocol),即简单对象访问协议。

Java领域的Web Service实现有很多种方式,例如sun公司的XML-RPC、Apache的Axis以及Codehaus的Xfire,但是这些都不适合在资源有限的移动设备中使用。早起的Java ME开发当中使用到了KSOAP。

下面我们将通过KSOAP和Apache HTTP客户端来实现一个天气预报。

1)、到Google的网站下载支持Android的KSOAP.jar文件

2)、将jar文件添加到工程的classpath下

weather.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TextView 
        android:text="天气预报"
        android:id="@+id/titleTextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <LinearLayout 
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView 
            android:text="请选择城市"
            android:id="@+id/cityTextView02"
            android:layout_width="wrap_content"
        	   android:layout_height="wrap_content" />
        <Spinner 
            android:id="@+id/citySpinner01"
            android:layout_width="fill_parent"
        	   android:layout_height="wrap_content" />
    </LinearLayout>
    <ScrollView 
        android:id="@+id/ScrollView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView 
            android:id="@+id/displayTextView03"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </ScrollView>
</LinearLayout>

WebServiceUtil.java

public class WebServiceUtil {
	//使用KSOAP,获得城市列表
	public static List<String> getCityList(){
		//命名空间
		String serviceNamespace = "http://WebXml.com.cn/";
		//请求URL
		String serviceURL = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx";
		//调用方法
		String methodName = "getRegionProvince";
		//实例化SoapObject对象
		SoapObject request = new SoapObject(serviceNamespace, methodName);
		//获得序列化的Envelope
		SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
		envelope.bodyOut = request;
		(new MarshalBase64()).register(envelope);
		//Android传输对象
		@SuppressWarnings("deprecation")
		AndroidHttpTransport ht = new AndroidHttpTransport(serviceURL);
		ht.debug = true;
		try {
			//调用
			ht.call("http://WebXml.com.cn/getRegionProvince", envelope);
			if(envelope.getResponse() != null){
				return parse(envelope.bodyIn.toString());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	//对得到的城市XMl信息进行解析
	private static List<String> parse(String str){
		String temp;
		List<String> list = new ArrayList<String>();
		if(str != null && str.length() > 0){
			int start = str.indexOf("string");
			int end = str.lastIndexOf(";");
			temp = str.substring(start, end - 3);
			String[] test = temp.split(";");
			for (int i = 0; i < test.length; i++) {
				if(i == 0){
					temp = test[i].substring(7);
				}else{
					temp = test[i].substring(8);
				}
				int index = temp.indexOf(",");
				list.add(temp.substring(0, index));
			}
		}
		return list;
	}
	//通过传递城市名称获得天气信息
	public static String getWeatherMsgByCity(String cityName){
		String url = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx/getWeather";
		HttpPost request = new HttpPost(url);
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("theCityCode", cityName));
		params.add(new BasicNameValuePair("theUserID", ""));
		String result = null;
		try {
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params,HTTP.UTF_8);
			request.setEntity(entity);
			HttpResponse response = new DefaultHttpClient().execute(request);
			if(response.getStatusLine().getStatusCode() == 200){
				result = EntityUtils.toString(response.getEntity());
				return parse2(result);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	//对天气信息XML文件进行解析
	private static String parse2(String str){
		String temp;
		String[] temps;
		List list = new ArrayList();
		StringBuilder sb = new StringBuilder("");
		if(str != null && str.length() > 0){
			temp = str.substring(str.indexOf("<string>"));
			temps = temp.split("</string>");
			for (int i = 0; i < temps.length; i++) {
				sb.append(temps[i].substring(12));
				sb.append("\n");
			}
		}
		return sb.toString();
	}
}

Activity

public class WeatherActivity extends Activity{
	private TextView displayTextView;
	private Spinner spinner;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.weather);
		displayTextView = (TextView) findViewById(R.id.displayTextView03);
		spinner = (Spinner) findViewById(R.id.citySpinner01);
		List<String> citys = WebServiceUtil.getCityList();
		ArrayAdapter a = new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item,citys);
		System.out.println("citys" + citys);
		spinner.setAdapter(a);
		
		spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				String msg = WebServiceUtil.getWeatherMsgByCity(spinner.getSelectedItem().toString());
				displayTextView.setText(msg);
				
			}
			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				
			}
		});
	}
}

五、直接使用WebView视图组件显示网页

Android提供了内置的浏览器,该浏览器使用了开源的WEbKit引擎。在Android中使用浏览器需要通过WebView组件来实现。WebView提供了一些浏览器方法,例如,使用loadUrl()可以直接打开一个Web地址页面;使用loadData可以显示HTML格式的网页内容。

1、使用WebView打开网页

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    
    <WebView 
        android:id="@+id/myWebView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>
public class TestWebViewActivity extends Activity {
	private WebView webView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		webView = (WebView) findViewById(R.id.myWebView);
//		String url = "http://www.google.com";
//		webView.loadUrl(url);
		
		//使用WebView加载HTML
		String html = "";
		html += "<html>";
		html += "<body>";
		html += "<a href=http://www.google.com>Google Home</a>";
		html += "</body>";
		html += "</html>";
		webView.loadData(html, "text/html", "utf-8");
	}
}

2、使用WebView加载HTML

见上面的实例
loadData(String data, String mimeType, String encoding);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值