为了在你的应用进行网络操作,你需要以下权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
在你增加网络功能之前,你需要确保数据和信息在你的应用里是安全的,通过网络传输。要做到以下几点:
· 您通过网络传输尽可能减少敏感或个人的的用户数据。
· 根据SSL发送所有的网络数据。
大部分的网络连接,android应用使用HTTP进行发送和接收数据。android平台包含的HttpsURLConnection端支持TLS,流上传和下载,超时时间配置,IPv6,连接池。
为了避免创建一个反应迟钝的UI,不要在UI线程上进行网络操作。默认android3.0(API level 11)和更高版本,在其他线程进行网络操作;如果你不想,会有一个NetworkOnMainThreadException异常。
下面的例子是通过一个不显示的fragment封装异步网络操作。
首先创建一个DownloadCallback接口
public interface DownloadCallback<T> {
interface Progress{
//错误
int ERROR = -1;
//连接成功
int CONNECT_SUCCESS = 0;
//获取inputstream成功
int GET_INPUT_STREAM_SUCCESS = 1;
//处理inputstream的进度
int PROCESS_INPUT_STREAM_IN_PROGRESS = 2;
//处理inputstream成功
int PROCESS_INPUT_STREAM_SUCCESS = 3;
}
//指示回调处理需要根据任务的结果更新其外观或信息。
// 预计将从主线程调用。
void updateFormDownload(T result);
//从NetworkInfo类获取设备网络状况
NetworkInfo getActiveNetWorkInfo();
//指示回调处理一些程序上的更新。
void onProgressUpdate(int progressCode,int percentComplete);
//指示下载操作完成。即使这个下载未完成也会调用该方法
void finishDownloading();
}
然后创建一个NetworkFragment
//实现一个无显示的Fragment,为了从网络上获取数据执行一个异步任务
public class NetworkFragment extends Fragment {
public static final String TAG = "NetworkFragment";
private static final String URL_KEY = "UrlKey";
private DownloadCallback mCallback;
private DownloadTask mDownloadTask;
private String mUrlString;
//静态初始化NetworkFragment,设置将要下载的URL
public static NetworkFragment getInstance(FragmentManager fragmentManager,String url){
NetworkFragment networkFragment = (NetworkFragment) fragmentManager
.findFragmentByTag(NetworkFragment.TAG);
if(networkFragment == null){
networkFragment = new NetworkFragment();
Bundle args = new Bundle();
args.putString(URL_KEY,url);
networkFragment.setArguments(args);
fragmentManager.beginTransaction().add(networkFragment,TAG).commit();
}
Log.d("networkFragment","networkFragment创建成功"+networkFragment);
return networkFragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在主活动的配置更改中保留此片段
setRetainInstance(true);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
//主activity发送一个callback
//从DownloadTask开始非阻塞执行
mUrlString = getArguments().getString(URL_KEY);
cancelDownload();
mCallback = (DownloadCallback) context;
mDownloadTask = new DownloadTask(mCallback);
mDownloadTask.execute(mUrlString);
}
@Override
public void onDetach() {
super.onDetach();
//清除引用的主activity,避免存储泄露
mCallback = null;
}
@Override
public void onDestroy() {
//当fragment销毁时,取消工作
cancelDownload();
super.onDestroy();
}
//取消一些正在执行的DownloadTask
public void cancelDownload() {
if(mDownloadTask!=null){
mDownloadTask.cancel(true);
}
}
}
创建异步进程类DownloadTask,并且使用HttpsUrlConnection获取数据。
public class DownloadTask extends AsyncTask<String,Void,DownloadTask.Result>{
private DownloadCallback mCallback;
DownloadTask(DownloadCallback callback){
setCallback(callback);
}
private void setCallback(DownloadCallback callback){
mCallback = callback;
}
//封装类作为结果和异常的连接。当下载工作完成了,
//完成或异常任选其一保证非空值。
//这允许你传递一个异常给UI线程
static class Result {
public String mResultValue;
public Exception mException;
public Result(String resultValue){
mResultValue = resultValue;
}
public Result(Exception mException){
this.mException = mException;
}
}
//取消后台网络运行如果我们没有网络连接
@Override
protected void onPreExecute() {
if(mCallback!=null){
NetworkInfo networkInfo = mCallback.getActiveNetWorkInfo();
if(networkInfo==null || !networkInfo.isConnected() || (networkInfo.getType()!= ConnectivityManager.TYPE_WIFI
&&networkInfo.getType()!=ConnectivityManager.TYPE_MOBILE)){
//如果没有连接,取消工作和下载作为空值回调
mCallback.updateFormDownload(null);
cancel(true);
}
}
}
//规定在后台执行网络工作
@Override
protected DownloadTask.Result doInBackground(String... urls) {
Result result = null;
if(!isCancelled() && urls!=null && urls.length>0){
String urlString = urls[0];
try {
URL url = new URL(urlString);
String resultString = downloadUrl(url);
if(resultString!=null){
result = new Result(resultString);
} else {
throw new IOException("没有接收响应");
}
} catch (Exception e) {
//传递给result一个异常
result = new Result(e);
}
}
return result;
}
//更新DownloadCallback结果
@Override
protected void onPostExecute(Result result) {
if(result!=null&&mCallback!=null){
if(result.mException!=null){
mCallback.updateFormDownload(result.mException.getMessage());
} else if(result.mResultValue!=null){
mCallback.updateFormDownload(result.mResultValue);
}
mCallback.finishDownloading();
}
}
//覆写一个特别的行为取消了后台线程
@Override
protected void onCancelled(Result result) {
}
private String downloadUrl(URL url) throws IOException {
InputStream stream = null;
HttpURLConnection connection = null;
String result = null;
try {
connection = (HttpURLConnection) url.openConnection();
//读取InputStream设置3000ms超时
connection.setReadTimeout(3000);
//连接设置3000ms超时
connection.setConnectTimeout(3000);
//设置请求方式为"GET"
connection.setRequestMethod("GET");
//默认为true,请求获取的时一个input body
connection.setDoInput(true);
connection.connect();
publishProgress(DownloadCallback.Progress.CONNECT_SUCCESS,0);
int responseCode = connection.getResponseCode();
if(responseCode!=HttpURLConnection.HTTP_OK){
throw new IOException("HTTP错误代码"+responseCode);
}
//获取InputStream
stream = connection.getInputStream();
publishProgress(DownloadCallback.Progress.GET_INPUT_STREAM_SUCCESS,0);
if(stream!=null){
//转换Stream为String最大长度为500
result = readStream(stream,500);
}
} finally {
//关闭Stream和切断HTTP连接
if(stream!=null){
stream.close();
}
if(connection!=null){
connection.disconnect();
}
}
return result;
}
//获取stream的处理操作
private String readStream(InputStream stream, int maxLegth) throws IOException{
String result = null;
//设置Inputstream为UTF-8
InputStreamReader reader = new InputStreamReader(stream,"UTF-8");
//创建一个临时的buffer 为了根据最大长度掌控数据
char[] buffer = new char[maxLegth];
//填入buffer
int numChars = 0;
int readSize = 0;
while (numChars1){
numChars += readSize;
int pct = (100*numChars)/maxLegth;
publishProgress(DownloadCallback.Progress.PROCESS_INPUT_STREAM_IN_PROGRESS,pct);
readSize = reader.read(buffer,numChars,buffer.length-numChars);
}
if(numChars!=-1){
//stream不为空
//如果实际长度小于最大长度,则创建响应体的实际长度
numChars = Math.min(numChars,maxLegth);
result = new String(buffer,0,numChars);
}
return result;
}
private void publishProgress(int processInputStreamInProgress, int pct) {
mCallback.onProgressUpdate(processInputStreamInProgress,pct);
}
}
最后在activity实例化fragment并复写DownloadCallback里面的方法
public class MainActivity extends FragmentActivity implements DownloadCallback{
private NetworkFragment mNetworkFragment;
//Boolean告诉我们在程序里是否有下载操作,避免重复操作。
private Boolean mDownloading = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNetworkFragment = NetworkFragment.getInstance(getSupportFragmentManager(),url);
startDownload();
}
private void startDownload(){
if(!mDownloading&&mNetworkFragment!=null){
//执行一个异步下载
mDownloading = true;
}
}
@Override
public void updateFormDownload(Object result) {
//根据下载的结果更新UI
}
@Override
public NetworkInfo getActiveNetWorkInfo() {
//获取设备网络信息
ConnectivityManager connectivityManager =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo;
}
@Override
public void onProgressUpdate(int progressCode, int percentComplete) {
switch (progressCode){
//你可以根据程序的更新,添加UI行为。
case Progress.ERROR:
break;
case Progress.CONNECT_SUCCESS:
break;
case Progress.PROCESS_INPUT_STREAM_IN_PROGRESS:
break;
case Progress.PROCESS_INPUT_STREAM_SUCCESS:
break;
}
}
@Override
public void finishDownloading() {
mDownloading = false;
if(mNetworkFragment!=null){
mNetworkFragment.cancelDownload();
}
}
}
摘自android developer