14.4 手机号码归属地查询

本文介绍如何在Android应用中通过调用Webservice查询手机号码归属地,讲解了使用http://webservice.webxml.com.cn提供的API和服务,并讨论了Android中主线程进行网络操作时会遇到的NetworkOnMainThreadException异常,提出了解决方案,包括使用StrictMode和在子线程中处理网络请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

手机号码归属地查询

MobileAddressQuery

Android通过调用Webservice实现手机号码归属地查询

 

注:http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx是本文webservice的提供商

具体的用法见:

http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo


android.os.NetworkOnMainThreadException

一个APP如果在主线程中请求网络操作,将会抛出此异常。Android这个设计是为了防止网络请求时间过长而导致界面假死的情况发生。

 

解决方案有两个,一个是使用StrictMode,二是使用线程来操作网络请求。

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">手机号码归属地查询</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="mobile">手机号码</string>
    <string name="button">归属地查询</string>
    <string name="error">查询失败</string>

</resources>

fragment_main.xml

<RelativeLayout 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"
    tools:context="com.example.mobileaddressquery.MainActivity$PlaceholderFragment" >

    <TextView
        android:id="@+id/lblMobile"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/mobile" />
    
    <EditText 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/lblMobile"
        android:id="@+id/mobile"/>
    
    <Button 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/button"
        android:id="@+id/buttonId"
        android:layout_below="@id/mobile"
        />
    
    <TextView
        android:id="@+id/lblResult"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/buttonId" />


</RelativeLayout>


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mobileaddressquery"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

    <!-- 访问Internet权限 -->  
    <uses-permission android:name="android.permission.INTERNET"/>  
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.mobileaddressquery.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

sop12.xml

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getMobileCodeInfo xmlns="http://WebXml.com.cn/">
      <mobileCode>$mobile</mobileCode>
      <userID></userID>
    </getMobileCodeInfo>
  </soap12:Body>
</soap12:Envelope>

AddressService.java

package com.example.mobileaddressquery;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.xmlpull.v1.XmlPullParser;

import android.util.Xml;

public class AddressService {

	private static String readSoapFile(InputStream inStream, String mobile)
			throws Exception {
		byte[] data = StreamTool.readInputStream(inStream);
		String soapxml = new String(data);
		Map<String, String> params = new HashMap<String, String>();
		params.put("mobile", mobile);
		return replace(soapxml, params);
	}

	public static String replace(String xml, Map<String, String> params)
			throws Exception {
		String result = xml;
		if (params != null && !params.isEmpty()) {
			for (Map.Entry<String, String> entry : params.entrySet()) {
				String name = "\\$" + entry.getKey();
				Pattern pattern = Pattern.compile(name);
				Matcher matcher = pattern.matcher(result);
				if (matcher.find()) {
					result = matcher.replaceAll(entry.getValue());
				}
			}
		}
		return result;
	}

	public static String getMobileAddress(InputStream inStream, String mobile)
			throws Exception {
		String soap = readSoapFile(inStream, mobile);
		byte[] data = soap.getBytes();
		URL url = new URL(
				"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx");
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("POST");
		conn.setConnectTimeout(5 * 1000);
		conn.setDoOutput(true);// 如果通过post提交数据,必须设置允许对外输出数据
		conn.setRequestProperty("Content-Type",
				"application/soap+xml; charset=utf-8");
		conn.setRequestProperty("Content-Length", String.valueOf(data.length));
		OutputStream outStream = conn.getOutputStream();
		outStream.write(data);
		outStream.flush();
		outStream.close();
		if (conn.getResponseCode() == 200) {
			return parseResponseXML(conn.getInputStream());
		}
		return null;
	}

	private static String parseResponseXML(InputStream inStream)
			throws Exception {
		XmlPullParser parser = Xml.newPullParser();
		parser.setInput(inStream, "UTF-8");
		int eventType = parser.getEventType();// 产生第一个事件
		while (eventType != XmlPullParser.END_DOCUMENT) {// 只要不是文档结束事件
			switch (eventType) {
			case XmlPullParser.START_TAG:
				String name = parser.getName();// 获取解析器当前指向的元素的名称
				if ("getMobileCodeInfoResult".equals(name)) {
					return parser.nextText();
				}
				break;
			}
			eventType = parser.next();
		}
		return null;
	}

}

StreamTool.java

package com.example.mobileaddressquery;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

public class StreamTool {

	/**
	 * 从输入流读取数据
	 * 
	 * @param inStream
	 * @return
	 * @throws Exception
	 */
	public static byte[] readInputStream(InputStream inStream) throws Exception {
		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = 0;
		while ((len = inStream.read(buffer)) != -1) {
			outSteam.write(buffer, 0, len);
		}
		outSteam.close();
		inStream.close();
		return outSteam.toByteArray();
	}

}

MainActivity.java

package com.example.mobileaddressquery;

import java.io.InputStream;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

	private EditText phoneSecEditText;
	private TextView resultView;
	private Button queryButton;
	private static final String TAG = "MainActivity";
	public MyThread thread;
	public Handler handler;

	@SuppressLint("HandlerLeak")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.fragment_main);

		phoneSecEditText = (EditText) this.findViewById(R.id.mobile);
		resultView = (TextView) this.findViewById(R.id.lblResult);
		queryButton = (Button) this.findViewById(R.id.buttonId);

		queryButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// 手机号码(段)
				String phoneSec = phoneSecEditText.getText().toString().trim();
				// 简单判断用户输入的手机号码(段)是否合法
				if ("".equals(phoneSec) || phoneSec.length() < 7) {
					// 给出错误提示
					phoneSecEditText.setError("您输入的手机号码(段)有误!");
					phoneSecEditText.requestFocus();
					// 将显示查询结果的TextView清空
					resultView.setText("");
					return;
				} else {
					Thread t = new MyThread();
					t.start();
				}

			}
		});

		// 创建handler对象
		handler = new Handler() {
			@SuppressLint("HandlerLeak")
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case 0x01:
					Bundle bundle = new Bundle();
					bundle = msg.getData();
					Toast.makeText(MainActivity.this,
							bundle.getString("result"), Toast.LENGTH_SHORT)
							.show();					
				}
			}
		};

	}

	// 创建线程
	public class MyThread extends Thread {
		@Override
		public void run() {
			// 创建本线程的消息队列并初始化
			Looper.prepare();
			getTelephoneInfo();
			// 开始运行消息队列
			Looper.loop();

		}
	}

	public void getTelephoneInfo() {
		// 查询手机号码(段)信息
		String mobile = phoneSecEditText.getText().toString();
		InputStream inStream = this.getClass().getClassLoader()
				.getResourceAsStream("sop12.xml");
		try {
			String address = AddressService.getMobileAddress(inStream, mobile);
			// 获取返回的结果
			Message msg = new Message();
			Bundle bundle = new Bundle();
			bundle.putString("result", address);
			msg.setData(bundle);
			msg.what = 0x01;
			handler.handleMessage(msg);

			// resultView.setText(address);
		} catch (Exception e) {
			e.printStackTrace();
			Log.e(TAG, e.toString());
			Toast.makeText(getApplicationContext(), R.string.error, 1).show();
		}
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值