【黑马Android】(05)短信/查询和添加/内容观察者使用/子线程网络图片查看器和Handler消息处理器/html查看器/使用HttpURLConnection采用Post方式请求数据/开源项目

备份短信和添加短信

操作系统短信的uri: content://sms/

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_SMS"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.itheima28.backupsms.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>
<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"
    tools:context=".MainActivity" >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:onClick="backupSms"
        android:text="备份短信" />

</RelativeLayout>
package com.itheima28.backupsms.entities;

public class SmsInfo {

	private int id;
	private String address;
	private long date;
	private int type;
	private String body;
	public SmsInfo(int id, String address, long date, int type, String body) {
		super();
		this.id = id;
		this.address = address;
		this.date = date;
		this.type = type;
		this.body = body;
	}
	@Override
	public String toString() {
		return "SmsInfo [id=" + id + ", address=" + address + ", date=" + date
				+ ", type=" + type + ", body=" + body + "]";
	}
	public SmsInfo() {
		super();
		// TODO Auto-generated constructor stub
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public long getDate() {
		return date;
	}
	public void setDate(long date) {
		this.date = date;
	}
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	public String getBody() {
		return body;
	}
	public void setBody(String body) {
		this.body = body;
	}
}
package com.itheima28.backupsms;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlSerializer;

import com.itheima28.backupsms.entities.SmsInfo;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.util.Xml;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

	}

	/**
	 * 备份短信
	 * @param v
	 */
	public void backupSms(View v) {
		// 1. 查出所有的短信
		Uri uri = Uri.parse("content://sms/");

		ContentResolver resolver = getContentResolver();
		Cursor cursor = resolver.query(uri, new String[]{"_id", "address", "date", "type", "body"}, null, null, null);

		if(cursor != null && cursor.getCount() > 0) {
			List<SmsInfo> smsList = new ArrayList<SmsInfo>();
			SmsInfo sms;

			while(cursor.moveToNext()) {	// 控制游标结果集的指针向下移一位, 当到最后一位, 停止.返回false
				sms = new SmsInfo();
				sms.setId(cursor.getInt(0));	// 设置短信的id
				sms.setAddress(cursor.getString(1));	// 设置短信的号码
				sms.setDate(cursor.getLong(2));	// 设置短信的日期
				sms.setType(cursor.getInt(3));	// 设置短信的类型, 接收1还是发送2
				sms.setBody(cursor.getString(4)); // 设置短信的内容
				smsList.add(sms);
			}
			cursor.close();

			// 2. 序列化到本地
			writeToLocal(smsList);
		}
	}

	/**
	 * 序列化到本地
	 */
	private void writeToLocal(List<SmsInfo> smsList) {

		try {
			XmlSerializer serializer = Xml.newSerializer();	// 得到序列化对象
			// 指定输出位置
			FileOutputStream fos = new FileOutputStream("/mnt/sdcard/sms.xml");
			serializer.setOutput(fos, "utf-8");

			serializer.startDocument("utf-8", true);

			serializer.startTag(null, "smss");

			for (SmsInfo smsInfo : smsList) {
				serializer.startTag(null, "sms");
				serializer.attribute(null, "id", String.valueOf(smsInfo.getId()));

				// 写号码
				serializer.startTag(null, "address");
				serializer.text(smsInfo.getAddress());
				serializer.endTag(null, "address");

				// 写时间
				serializer.startTag(null, "date");
				serializer.text(String.valueOf(smsInfo.getDate()));
				serializer.endTag(null, "date");

				//写类型
				serializer.startTag(null, "type");
				serializer.text(String.valueOf(smsInfo.getType()));
				serializer.endTag(null, "type");

				// 写内容
				serializer.startTag(null, "body");
				serializer.text(smsInfo.getBody());
				serializer.endTag(null, "body");

				serializer.endTag(null, "sms");
			}

			serializer.endTag(null, "smss");

			serializer.endDocument();

			Toast.makeText(this, "备份成功", 0).show();
		} catch (Exception e) {
			Toast.makeText(this, "备份失败", 0).show();
			e.printStackTrace();
		}

	}
}

相亲神器

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.WRITE_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.itheima28.xiangqin.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>
package com.itheima28.xiangqin;

import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.app.Activity;
import android.content.ContentValues;
import android.view.Menu;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 停10秒钟, 想系统短信数据库中写一条短信
		new Thread(new Runnable() {
			@Override
			public void run() {
				SystemClock.sleep(10 * 1000);

				Uri uri = Uri.parse("content://sms/");	// 操作sms表的uri

				ContentValues values = new ContentValues();
				values.put("address", "95555");
				values.put("type", "1");
				values.put("body", "您的尾号为8890的账户, 收到100, 000, 000, 000.00元的转账. 活期余额为: 899, 777, 000, 111, 000.00元");
				getContentResolver().insert(uri, values);
			}
		}).start();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

查询和添加联系人

查询联系人:raw_contacts, data

查询:

1. 去raw_contacts表中取所有联系人的_id

2. 去data表中根据上面取到的_id查询对应id的数据.

content://com.android.contacts/raw_contacts

content://com.android.contacts/data

<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:orientation="vertical"
    tools:context=".MainActivity" >

    <Button
        android:onClick="queryContacts"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="查询所有联系人" />

    <Button
        android:onClick="addContacts"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="添加联系人" />

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.itheima28.contacts.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>
package com.itheima28.contacts;

import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {

	private static final String TAG = "MainActivity";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	private void printCursor(Cursor cursor) {
		if(cursor != null && cursor.getCount() > 0) {

			while(cursor.moveToNext()) {

				int columnCount = cursor.getColumnCount(); // 列的总数

				for (int i = 0; i < columnCount; i++) {
					String columnName = cursor.getColumnName(i);	// 取对应i位置的列的名称
					String columnValue = cursor.getString(i); // 取出对应i位置的列的值

					Log.i(TAG, "当前是第" + cursor.getPosition() + "行: " + columnName + " = " + columnValue);
				}
			}
			cursor.close();
		}
	}

	/**
	 * 查询联系人
	 * @param v
	 */
	public void queryContacts(View v) {
		// 1. 去raw_contacts表中取所有联系人的_id
		Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
		Uri dataUri = Uri.parse("content://com.android.contacts/data");

		Cursor cursor = getContentResolver().query(uri, new String[]{"_id"}, null, null, null);
//		printCursor(cursor);
		if(cursor != null && cursor.getCount() > 0) {

			while(cursor.moveToNext()) {
				int id = cursor.getInt(0);
				// 2. 去data表中根据上面取到的_id查询对应id的数据.

				String selection = "raw_contact_id = ?";
				String[] selectionArgs = {String.valueOf(id)};
				Cursor c = getContentResolver().query(dataUri, new String[]{"data1", "mimetype"},
						selection, selectionArgs, null);
				if(c != null && c.getCount() > 0) {

					while(c.moveToNext()) {
						String mimetype = c.getString(1);		// 当前取的是mimetype的值
						String data1 = c.getString(0);		// 当前取的是data1数据

						if("vnd.android.cursor.item/phone_v2".equals(mimetype)) {
							Log.i(TAG, "号码: " + data1);
						} else if("vnd.android.cursor.item/name".equals(mimetype)) {
							Log.i(TAG, "姓名: " + data1);
						} else if("vnd.android.cursor.item/email_v2".equals(mimetype)) {
							Log.i(TAG, "邮箱: " + data1);
						}
					}
					c.close();
				}
			}
			cursor.close();
		}

	}

	public void addContacts(View v) {
		Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
		Uri dataUri = Uri.parse("content://com.android.contacts/data");
		// 1. 在raw_contacts表中添加一个记录

		// 取raw_contacts表中contact_id的值
		Cursor cursor = getContentResolver().query(uri, new String[]{"contact_id"}, null, null, "contact_id desc limit 1");
		if(cursor != null && cursor.moveToFirst()) {
			int contact_id = cursor.getInt(0);
			contact_id ++;
			cursor.close();

			ContentValues values = new ContentValues();
			values.put("contact_id", contact_id);
			getContentResolver().insert(uri, values);

			// 2. 根据上面添加记录的id, 取data表中添加三条数据

			// 存号码
			values = new ContentValues();
			values.put("mimetype", "vnd.android.cursor.item/phone_v2");
			values.put("data1", "10086");
			values.put("raw_contact_id", contact_id);
			getContentResolver().insert(dataUri, values);

			// 存姓名
			values = new ContentValues();
			values.put("mimetype", "vnd.android.cursor.item/name");
			values.put("data1", "中国移动");
			values.put("raw_contact_id", contact_id);
			getContentResolver().insert(dataUri, values);

			// 存邮箱
			values = new ContentValues();
			values.put("mimetype", "vnd.android.cursor.item/email_v2");
			values.put("data1", "[email protected]");
			values.put("raw_contact_id", contact_id);
			getContentResolver().insert(dataUri, values);
		}

	}
}

内容观察者使用

内容观察者:

发件箱的uri:content://sms/outbox

package com.itheima28.contentobserverdemo;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 监听系统短信
		ContentResolver resolver = getContentResolver();

		// 注册一个内容观察者观察短信数据库
		resolver.registerContentObserver(Uri.parse("content://sms/"), true, new MyContentObserver(new Handler()));
	}

	/**
	 * @author andong
	 * 内容观察者
	 */
	class MyContentObserver extends ContentObserver {

		private static final String TAG = "MyContentObserver";

		public MyContentObserver(Handler handler) {
			super(handler);
		}

		/**
		 * 当被监听的内容发生改变时回调
		 */
		@Override
		public void onChange(boolean selfChange) {
			Log.i(TAG, "短信改变了");
			Uri uri = Uri.parse("content://sms/outbox");	// 发件箱的uri

			// 查询发件箱的内容
			Cursor cursor = getContentResolver().query(uri, new String[]{"address", "date", "body"}, null, null, null);
			if(cursor != null && cursor.getCount() > 0) {

				String address;
				long date;
				String body;
				while(cursor.moveToNext()) {
					address = cursor.getString(0);
					date = cursor.getLong(1);
					body = cursor.getString(2);

					Log.i(TAG, "号码: " + address + ", 日期: " + date + ", 内容: " + body);
				}
				cursor.close();
			}
		}
	}
}

网络图片查看器

Android notResponding(应用程序无响应) 阻塞了主线程 ANR异常

异常:

CalledFromWrongThreadException: Only theoriginal thread that created a view hierarchy can touch its views.

只有原始的线程(主线程, ui线程)才能修改view对象.

在子线程中修改view的显示状态, 会报上面异常.

子线程网络图片查看器和Handler消息处理器

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
<!--     访问网络的权限 -->
    <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.itheima28.netphoto.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>
<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:orientation="vertical"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/et_url"
            android:layout_width="0dip"
            android:text="http://imgstatic.baidu.com/img/image/d833c895d143ad4bf450b6dd80025aafa40f06b4_%E5%89%AF%E6%9C%AC.jpg"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:layout_weight="1" />

        <Button
            android:id="@+id/btn_submit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Go"
            android:textSize="20sp" />
    </LinearLayout>

</LinearLayout>
package com.itheima28.netphoto;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

	private static final String TAG = "MainActivity";
	protected static final int ERROR = 1;
	private EditText etUrl;
	private ImageView ivIcon;
	private final int SUCCESS = 0;

	private Handler handler = new Handler() {

		/**
		 * 接收消息
		 */
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);

			Log.i(TAG, "what = " + msg.what);
			if(msg.what == SUCCESS) {	// 当前是访问网络, 去显示图片
				ivIcon.setImageBitmap((Bitmap) msg.obj);		// 设置imageView显示的图片
			} else if(msg.what == ERROR) {
				Toast.makeText(MainActivity.this, "抓去失败", 0).show();
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		ivIcon = (ImageView) findViewById(R.id.iv_icon);
		etUrl = (EditText) findViewById(R.id.et_url);

		findViewById(R.id.btn_submit).setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		final String url = etUrl.getText().toString();

		new Thread(new Runnable() {

			@Override
			public void run() {
				Bitmap bitmap = getImageFromNet(url);

//				ivIcon.setImageBitmap(bitmap);		// 设置imageView显示的图片
				if(bitmap != null) {
					Message msg = new Message();
					msg.what = SUCCESS;
					msg.obj = bitmap;
					handler.sendMessage(msg);
				} else {
					Message msg = new Message();
					msg.what = ERROR;
					handler.sendMessage(msg);
				}
			}}).start();

	}

	/**
	 * 根据url连接取网络抓去图片返回
	 * @param url
	 * @return url对应的图片
	 */
	private Bitmap getImageFromNet(String url) {
		HttpURLConnection conn = null;
		try {
			URL mURL = new URL(url);	// 创建一个url对象

			// 得到http的连接对象
			conn = (HttpURLConnection) mURL.openConnection();

			conn.setRequestMethod("GET");		// 设置请求方法为Get
			conn.setConnectTimeout(10000);		// 设置连接服务器的超时时间, 如果超过10秒钟, 没有连接成功, 会抛异常
			conn.setReadTimeout(5000);		// 设置读取数据时超时时间, 如果超过5秒, 抛异常

			conn.connect();		// 开始链接

			int responseCode = conn.getResponseCode(); // 得到服务器的响应码
			if(responseCode == 200) {
				// 访问成功
				InputStream is = conn.getInputStream();	// 获得服务器返回的流数据

				Bitmap bitmap = BitmapFactory.decodeStream(is); // 根据 流数据 创建一个bitmap位图对象

				return bitmap;
			} else {
				Log.i(TAG, "访问失败: responseCode = " + responseCode);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(conn != null) {
				conn.disconnect();		// 断开连接
			}
		}
		return null;
	}
}

html查看器

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <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.itheima28.htmldemo.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>
<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:orientation="vertical"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/et_url"
            android:layout_width="0dip"
            android:text="http://www.baidu.com"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:layout_weight="1" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="getHtml"
            android:text="GO" />
    </LinearLayout>

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <TextView
            android:id="@+id/tv_html"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </ScrollView>

</LinearLayout>

package com.itheima28.htmldemo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private static final String TAG = "MainActivity";
	private static final int SUCCESS = 0;
	protected static final int ERROR = 1;
	private EditText etUrl;
	private TextView tvHtml;

	private Handler handler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case SUCCESS:
				 tvHtml.setText((String) msg.obj);
				break;
			case ERROR:
				Toast.makeText(MainActivity.this, "访问失败", 0).show();
				break;
			default:
				break;
			}
		}

	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		etUrl = (EditText) findViewById(R.id.et_url);
		tvHtml = (TextView) findViewById(R.id.tv_html);

	}

	public void getHtml(View v) {
		final String url = etUrl.getText().toString();

		new Thread(new Runnable() {

			@Override
			public void run() {
				// 请求网络
				String html = getHtmlFromInternet(url);

				if(!TextUtils.isEmpty(html)) {
					// 更新textview的显示了
					Message msg = new Message();
					msg.what = SUCCESS;
					msg.obj = html;
					handler.sendMessage(msg);
				} else {
					Message msg = new Message();
					msg.what = ERROR;
					handler.sendMessage(msg);
				}
			}
		}).start();
	}

	/**
	 * 根据给定的url访问网络, 抓去html代码
	 * @param url
	 * @return
	 */
	protected String getHtmlFromInternet(String url) {

		try {
			URL mURL = new URL(url);
			HttpURLConnection conn = (HttpURLConnection) mURL.openConnection();

			conn.setRequestMethod("GET");
			conn.setConnectTimeout(10000);
			conn.setReadTimeout(5000);

//			conn.connect();

			int responseCode = conn.getResponseCode();

			if(responseCode == 200) {
				InputStream is = conn.getInputStream();
				String html = getStringFromInputStream(is);
				return html;
			} else {
				Log.i(TAG, "访问失败: " + responseCode);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 根据流返回一个字符串信息
	 * @param is
	 * @return
	 * @throws IOException
	 */
	private String getStringFromInputStream(InputStream is) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;

		while((len = is.read(buffer)) != -1) {
			baos.write(buffer, 0, len);
		}
		is.close();

		String html = baos.toString();	// 把流中的数据转换成字符串, 采用的编码是: utf-8

		String charset = "utf-8";
		if(html.contains("gbk") || html.contains("gb2312")
				|| html.contains("GBK") || html.contains("GB2312")) {		// 如果包含gbk, gb2312编码, 就采用gbk编码进行对字符串编码
			charset = "gbk";
		}

		html = new String(baos.toByteArray(), charset);	// 对原有的字节数组进行使用处理后的编码名称进行编码
		baos.close();
		return html;
	}
}

html查看器乱码问题

	/**
	 * 根据流返回一个字符串信息
	 * @param is
	 * @return
	 * @throws IOException
	 */
	private String getStringFromInputStream(InputStream is) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;

		while((len = is.read(buffer)) != -1) {
			baos.write(buffer, 0, len);
		}
		is.close();

		String html = baos.toString();	// 把流中的数据转换成字符串, 采用的编码是: utf-8

		String charset = "utf-8";
		if(html.contains("gbk") || html.contains("gb2312")
				|| html.contains("GBK") || html.contains("GB2312")) {		// 如果包含gbk, gb2312编码, 就采用gbk编码进行对字符串编码
			charset = "gbk";
		}

		html = new String(baos.toByteArray(), charset);	// 对原有的字节数组进行使用处理后的编码名称进行编码
		baos.close();
		return html;
	}

使用HttpURLConnection采用Post方式请求数据

Servlet服务器程序

package com.itheima28.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginServlet extends HttpServlet {

	/**
	 * The doGet method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to get.
	 *
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String username = request.getParameter("username");	// 采用的编码是: iso-8859-1
		String password = request.getParameter("password");

		// 采用iso8859-1的编码对姓名进行逆转, 转换成字节数组, 再使用utf-8编码对数据进行转换, 字符串
		username = new String(username.getBytes("iso8859-1"), "utf-8");
		password = new String(password.getBytes("iso8859-1"), "utf-8");

		System.out.println("姓名: " + username);
		System.out.println("密码: " + password);

		if("lisi".equals(username) && "123".equals(password)) {
			/*
			 * getBytes 默认情况下, 使用的iso8859-1的编码, 但如果发现码表中没有当前字符,
			 * 会使用当前系统下的默认编码: GBK
			 */
			response.getOutputStream().write("登录成功".getBytes("utf-8"));
		} else {
			response.getOutputStream().write("登录失败".getBytes("utf-8"));
		}
	}

	/**
	 * The doPost method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to post.
	 *
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("doPost");
		doGet(request, response);
	}

}

Android客户端

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <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.itheim28.submitdata.MainActivity2"
            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>

<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:orientation="vertical"
    tools:context=".MainActivity" >

    <EditText
        android:id="@+id/et_username"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="请输入姓名" />

    <EditText
        android:id="@+id/et_password"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="请输入密码" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="doGet"
        android:text="Get方式提交" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="doPost"
        android:text="Post方式提交" />
</LinearLayout>
package com.itheim28.submitdata.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import android.util.Log;

public class NetUtils {

	private static final String TAG = "NetUtils";

	/**
	 * 使用post的方式登录
	 * @param userName
	 * @param password
	 * @return
	 */
	public static String loginOfPost(String userName, String password) {
		HttpURLConnection conn = null;
		try {
			URL url = new URL("http://10.0.2.2:8080/ServerItheima28/servlet/LoginServlet");

			conn = (HttpURLConnection) url.openConnection();

			conn.setRequestMethod("POST");
			conn.setConnectTimeout(10000); // 连接的超时时间
			conn.setReadTimeout(5000); // 读数据的超时时间
			conn.setDoOutput(true);	// 必须设置此方法, 允许输出
//			conn.setRequestProperty("Content-Length", 234);		// 设置请求头消息, 可以设置多个

			// post请求的参数
			String data = "username=" + userName + "&password=" + password;

			// 获得一个输出流, 用于向服务器写数据, 默认情况下, 系统不允许向服务器输出内容
			OutputStream out = conn.getOutputStream();
			out.write(data.getBytes());
			out.flush();
			out.close();

			int responseCode = conn.getResponseCode();
			if(responseCode == 200) {
				InputStream is = conn.getInputStream();
				String state = getStringFromInputStream(is);
				return state;
			} else {
				Log.i(TAG, "访问失败: " + responseCode);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(conn != null) {
				conn.disconnect();
			}
		}
		return null;
	}

	/**
	 * 使用get的方式登录
	 * @param userName
	 * @param password
	 * @return 登录的状态
	 */
	public static String loginOfGet(String userName, String password) {
		HttpURLConnection conn = null;
		try {
			String data = "username=" + URLEncoder.encode(userName) + "&password=" + URLEncoder.encode(password);
			URL url = new URL("http://10.0.2.2:8080/ServerItheima28/servlet/LoginServlet?" + data);
			conn = (HttpURLConnection) url.openConnection();

			conn.setRequestMethod("GET");		// get或者post必须得全大写
			conn.setConnectTimeout(10000); // 连接的超时时间
			conn.setReadTimeout(5000); // 读数据的超时时间

			int responseCode = conn.getResponseCode();
			if(responseCode == 200) {
				InputStream is = conn.getInputStream();
				String state = getStringFromInputStream(is);
				return state;
			} else {
				Log.i(TAG, "访问失败: " + responseCode);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(conn != null) {
				conn.disconnect();		// 关闭连接
			}
		}
		return null;
	}

	/**
	 * 根据流返回一个字符串信息
	 * @param is
	 * @return
	 * @throws IOException
	 */
	private static String getStringFromInputStream(InputStream is) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;

		while((len = is.read(buffer)) != -1) {
			baos.write(buffer, 0, len);
		}
		is.close();

		String html = baos.toString();	// 把流中的数据转换成字符串, 采用的编码是: utf-8

//		String html = new String(baos.toByteArray(), "GBK");

		baos.close();
		return html;
	}
}
package com.itheim28.submitdata;

import com.itheim28.submitdata.utils.NetUtils;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

	private EditText etUserName;
	private EditText etPassword;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		etUserName = (EditText) findViewById(R.id.et_username);
		etPassword = (EditText) findViewById(R.id.et_password);
	}

	public void doGet(View v) {
		final String userName = etUserName.getText().toString();
		final String password = etPassword.getText().toString();

		new Thread(
				new Runnable() {

					@Override
					public void run() {
						// 使用get方式抓去数据
						final String state = NetUtils.loginOfGet(userName, password);

						// 执行任务在主线程中
						runOnUiThread(new Runnable() {
							@Override
							public void run() {
								// 就是在主线程中操作
								Toast.makeText(MainActivity.this, state, 0).show();
							}
						});
					}
				}).start();
	}

	public void doPost(View v) {
		final String userName = etUserName.getText().toString();
		final String password = etPassword.getText().toString();

		new Thread(new Runnable() {
			@Override
			public void run() {
				final String state = NetUtils.loginOfPost(userName, password);
				// 执行任务在主线程中
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						// 就是在主线程中操作
						Toast.makeText(MainActivity.this, state, 0).show();
					}
				});
			}
		}).start();
	}
}

开源项目简介

github.com 开源网站, 一个大的仓库. 存放的都是框架

android-async-http-master.zip

android-smart-image-view-master.zip

直接拿来用 最火的android开源项目  csdn的帖子

时间: 2024-10-19 18:26:53

【黑马Android】(05)短信/查询和添加/内容观察者使用/子线程网络图片查看器和Handler消息处理器/html查看器/使用HttpURLConnection采用Post方式请求数据/开源项目的相关文章

Android中子线程网络查看器与Handler消息处理器

xml文件代码部分 <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&quo

Android之——短信的备份与还原

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47091281 目前,Android手机中的一些软件可以实现手机短信的备份与还原操作.这篇博文就是要向大家介绍如何实现Android短信的备份与还原操作.好了,相信大家对这些实用的功能还是比较感兴趣的,不多说了,我们直接进入主题吧. 一.原理 我的实现原理很简单,界面上放置几个TextView列表,其中两项为"短信的备份"和"短信的还原",点击&quo

Android获取短信验证码

Android开发中关于短息验证码的设计层出不穷,越来越多的应用为了更好的提高软件的安全性,开始使用通过服务器向用户发送验证码的方式,来保护用户个人信息的安全性.无论是用户注册时的信息验证还是当用户发出找回密码请求时的短信验证,他们的工作原理大致上是一致的,因为项目的需要研究了一下关于这方面的知识,本篇我将带领大家一起实现这一当下流行的设计方案. 众所周知,短信验证需要服务器端生成一个验证码,然后发送到用户输入的手机上,这个过程需要服务器主动向客户发送验证短信,所以这是就需要一个移动或联通的发送

Android开发短信备份小例子

主要是使用内容提供者ContentProvider #1.在activity_main.xml布局文件中添加写sdcard权限,并添加读短信的权限 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_par

android发送短信例子

Android应用开发中我们常常需要发送手机短信.这对于android平台来说,是最简单不过的功能了,无需太多代码,也无需自定义代码,只需要调用android提供的消息管理类SmsManager就可以了. [源码下载]http://www.code4apk.com/android-code/202 核心就是使用SmsManager的sendTextMessage方法加上PendingIntent跳转. 核心代码如下: SmsManager sms=SmsManager.getDefault();

Android之短信验证

一.目标 实现Android短信验证 二.下面用一个简单的案例来完成这个功能 1.首先下载短信验证SDK 下载短信验证SDK官网地址:http://www.mob.com 找到SDK下载,在SMS里找到"SMSSDK For Android"下载, 如图: 2.下载完成之后: 将SMSSDK文件夹下的两个.jar文件和.aar文件复制到你项目的Project->app->libs目录下 如图所示: 3.在Android->Gradle Scripts->buli

android 定时短信app之时间选择器(一)

DatePicker类图 主要方法 public void init(int year, int monthOfYear, int dayOfMonth, DatePicker.OnDateChangedListener onDateChangedListener) 类 TimePicker类图 setOnTimeChangedListener public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener onTime

用Xposed框架拦截Android操作系统的短信接收

短信接收原理 关于Android操作系统短信的接收和发送流程的文章网上有一大堆,但是真正说得很清楚的不多,这篇blog写得不错.其实要想真正弄懂Android操作系统短信的流程,还是Linus的那句话: Read the fucking source code.呵呵 在Android操作系统中,大部分敏感信息的传递过程都是基于binder机制的,当然SMS也不例外.对于SMS的接收流程的描述从Framework层和Application层这两个层面进行介绍. Framework层 当短信到达Fr

奔跑吧兄弟中奖短信查询

奔跑吧兄弟中奖短信查询[010一5670一8820]人民法院咨询电话:010一5670一8820[人民法院] 温馨提示:(抽奖活动如获奖 请拨打以下法院电话核实):010一5670一8820 法院是国家的一项法律制度.在我国,法院是指国家专门设立的法院机构,根 据法律的规定和当事人的申请,按照法定程序证明法律行为,有法律意义的事件, 文书的真实性和合法性,以及其他与法院有关的法律事务的非诉讼活动. 法院电话::010一5670一8820 法院活动有四大基本特征: (1)法院是由国家专门司法证明机