Android之网络下载与图片解码-----网络图片浏览器

2022-06-14 08:29:35 浏览数 (1)

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下载完毕后就里面发出一个事件通知主线程数据下载完毕,并及时的解码和显示。后续再改进。

0 人点赞