1.Android系统网络,与其他系统一样,主要分低级别的socket编程和基于协议的http编程。当然http编程也是基于socket编程的。由于tcp/IP 协议栈是一致的,所以各个平台网络编程流程和思想是一样的,只是接口不同而已。
2.android的媒体库已经完成了图片,音视频解码,图片解码主要是BitmapFactory库来完成,解码处理的位图在再imageView进行展示即可
3.由于网络涉及到用户的隐私权限,所以必须在清单文件中注册
<uses-permission android:name="android.permission.INTERNET" />
3.Android 3.0 以后,不允许在主线程中下载,必需开启一个子线程来完成网络下载动作,如果硬要在主线程完成网络下载,必须在代码中申请权限。
在开发中,为了防止访问网络阻塞主线程,一般都要把访问网络放在独立线程中或者异步线程AsyncTask中。但是由于某些原因,想要忽略这些强制策略问题的话,可以在onCreate()方法里面加上 StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); 就可以解决该问题。另外在类的前面,要加上@SuppressLint("NewApi")才行。
清单文件如下:
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.httpdowload"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/show"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:screenOrientation="portrait"
android:name="com.example.httpdowload.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>
所用的字符串
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">HttpShow</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="url">请输入网址</string>
<string name="show">图片显示</string>
</resources>
布局文件如下:
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#808080"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/url"
android:textSize="15sp"
android:textColor="#ffffff"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="30sp"
android:inputType="textUri"
android:background="#000000"
android:layout_margin="4sp"
android:id="@ id/edittext"
android:textColor="#ffffff"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/show"
android:textSize="15sp"
android:textColor="#ffffff"
android:id="@ id/button"
/>
<ImageView
android:id="@ id/image"
android:scaleType="centerCrop"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:maxWidth="500sp"
android:maxHeight="750sp"
android:contentDescription="@string/show"
android:src="@drawable/bg"
android:background="#00fa9a"
/>
</LinearLayout >
主activity代码如下:
代码语言:javascript复制package com.example.httpdowload;
import com.example.httpservice.httpservice;
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.ImageView;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.StrictMode;
public class MainActivity extends ActionBarActivity {
private EditText text;
private Button button;
private ImageView image;
private String path;
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text=(EditText)this.findViewById(R.id.edittext);
button=(Button)this.findViewById(R.id.button);
image=(ImageView) this.findViewById(R.id.image);
button.setOnClickListener(listener);
StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
private OnClickListener listener =new OnClickListener()
{
@Override
public void onClick(View v) {
Button bx=(Button) v;
switch(bx.getId())
{
case R.id.button :
path=text.getText().toString();
try {
Log.i("mytag","network connetct is begin!");
byte[]Data = httpservice.download(path);
Bitmap bitmap=BitmapFactory.decodeByteArray(Data, 0, Data.length);
image.setImageBitmap(bitmap);
}
catch (Exception e)
{
Log.e("mytag","Error is happen!");
e.printStackTrace();
}
break;
default:
break;
}
}
};
}
网络下载代码如下:
代码语言:javascript复制package com.example.httpservice;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.util.Log;
public class httpservice {
public static byte[] download(String path) throws Exception
{
URL url=new URL(path);
Log.i("mynet",path);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
Log.i("mynet","wait for the response!");
Log.e("mynet","code=" conn.getResponseCode());
if(conn.getResponseCode()==200)
{
Log.i("mynet","netwok is connect success!");
InputStream inStream=conn.getInputStream();
return DataGet.read(inStream);
}
else
{
Log.e("mynet","network is connetct failed" "code" conn.getResponseCode());
}
return null;
}
}
网路读数据代码如下:
代码语言:javascript复制package com.example.httpservice;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import android.util.Log;
public class DataGet {
public static byte[] read(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
int count =0;
while( (len = inStream.read(buffer)) != -1){
outStream.write(buffer, 0, len);
count ;
}
Log.i("data","data is read finish" count);
inStream.close();
return outStream.toByteArray();
}
}
效果如下:
以上代码将网络下载,与ACtivity放在一个线程中,如果图片很大会影响效率。这里创建一个子线程专门用来网络下载。
代码语言:javascript复制package com.example.httpdowload;
import com.example.httpservice.httpservice;
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.ImageView;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.StrictMode;
public class MainActivity extends ActionBarActivity {
private EditText text;
private Button button;
private ImageView image;
private String path;
byte[]Data;
Bitmap bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text=(EditText)this.findViewById(R.id.edittext);
button=(Button)this.findViewById(R.id.button);
image=(ImageView) this.findViewById(R.id.image);
button.setOnClickListener(listener);
/* StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy); 如果让下载代码在主线程中跑,需要在系统中申请该权限,因为
Android 3.0 以后,不允许在主线程中下载,必需开启一个子线程来完成网络下载动作*/
}
private OnClickListener listener =new OnClickListener()
{
@Override
public void onClick(View v) {
Button bx=(Button) v;
switch(bx.getId())
{
case R.id.button :
path=text.getText().toString();
try {
Log.i("mytag","network connetct is begin thread!");
/*byte[]Data = httpservice.download(path);*/
Thread t =new Thread(new Runnable()
{
public void run() {
try {
Data = httpservice.download(path);
bitmap=BitmapFactory.decodeByteArray(Data, 0, Data.length);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(3000);
image.setImageBitmap(bitmap);
}
catch (Exception e)
{
Log.e("mytag","Error is happen!");
e.printStackTrace();
}
break;
default:
break;
}
}
};
}
该方法还存在无问题,也就是线程下载完图片数据后,如何及时通知主线程解码呢?因为主线程也不能查询下载完毕的状态,从而达到下载和解码的同步,这里暂且用2s 延时来等等下载完毕,但有时网络不好,3s延时也不够用。造成第一次点击button后,没图片显示,必需第二次后才显示。
以上通过延时方法来同步会影响体验性,无法达成下载和解码准确同步。
规范的做法应该是创建一个service来下载,在service创建一个线程做下载,而后主线程订阅这个事件,这样service下载完毕后就里面发出一个事件通知主线程数据下载完毕,并及时的解码和显示。后续再改进。