網絡圖片查看器:(讀取網絡圖片,但是每次都是在執行.getResponseCode()方法的時候拋出異常)
找出問題點了,在MainActivity中調用這個類的網絡操作方法,可能會導致activity的一些問題,谷歌從在android2.3版本以後,系統增加了一個類:StrictMode。這個類對網絡的訪問方式進行了一定的改變。
StrictMode通常用於捕獲磁盤訪問或者網絡訪問中與主進程之間交互產生的問題,因爲在主進程中,UI操作和一些動作的執行是最經常用到的,它們之間會產生一定的衝突問題。將磁盤訪問和網絡訪問從主線程中剝離可以使磁盤或者網絡的訪問更加流暢,提升響應度和用戶體驗。
如果一定要這樣操作的話,需要在MainActivity中加入如下代碼:
StrictMode.setThreadPolicy(new
StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(
new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
並且在配置文件中將SDK的最低等級設爲11
詳細實現代碼如下:
MainActivity.java類,實現主界面。有兩個按鈕分別對應不同的功能,一個按鈕是通過內部類實現的點擊事件處理,一個是通過配置設置的點擊函數實現的事件處理。
package com.example.netimage;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button=(Button) this.findViewById(R.id.imagebutton);
button.setOnClickListener(new ButtonOnclickListener());
}
public void openOterProcess(View v)
{
Log.i("testOpenOterProcess","the meth is Ok");
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName("dbSQLiteOPenHelper/dateoperate", "dateOperate");
intent.setComponent(cn);
startActivity(intent);
}
private final class ButtonOnclickListener implements View.OnClickListener
{
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setClass(MainActivity.this, NetImageActivity.class);
startActivity(intent);
}
}
@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;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
下面主要是顯示圖片的activity,有些Log.i()函數,是我用來測試發現問題用的。剛剛開始老會出現在執行.getResponseCode()方法的時候拋出異常(已解決).
package com.example.netimage;
import com.example.service.ImageService;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
public class NetImageActivity extends Activity {
private EditText pathText;
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_netimage);
//將磁盤訪問和網絡訪問從主線程中剝離可以使磁盤或者網絡的訪問更加流暢,提升響應度和用戶體驗。
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy
.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode
.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
pathText = (EditText)this.findViewById(R.id.imagepath);
imageView = (ImageView)this.findViewById(R.id.imageview);
Button button=(Button) this.findViewById(R.id.button);
button.setOnClickListener(new ButtonOnclickListener());
}
private final class ButtonOnclickListener implements View.OnClickListener
{
@Override
public void onClick(View v) {
String path=pathText.getText().toString();
try {
Log.i("testGetimage", "onClick正常");
byte[] data = ImageService.getImage(path);
Log.i("testGetimage", "ImageService正常");
Bitmap bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);
imageView.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), R.string.failed, 1).show();
}
}
}
@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;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
獲取網絡圖片的數據。package com.example.service;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.util.Log;
import com.example.utils.StreamTool;
public class ImageService {
/*
* 獲取網絡圖片的數據
* @param path網絡圖片路徑
* @return
*/
public static byte[] getImage(String path) throws Exception{
URL url=new URL(path);
Log.i("testGetimage", url.toString());
HttpURLConnection conn=(HttpURLConnection)url.openConnection();//基於HTTP協議的鏈接對象
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode()==200)
{
InputStream instream=conn.getInputStream();
Log.i("testGetimage", "IO正常");
return StreamTool.read(instream);
}else{
Log.i("testGetimage", "IO異常");
}
return null;
}
}
imageService中的工具類實現。package com.example.utils;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class StreamTool {
public static byte[] read(InputStream instream) throws Exception{
ByteArrayOutputStream outStream=new ByteArrayOutputStream();
byte[] buffer=new byte[1024];
int len=0;
while((len=instream.read(buffer))!=-1)
{
outStream.write(buffer,0,len);
}
instream.close();
return outStream.toByteArray();
}
}
佈局設置(layout文件)
一:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/imagepath"/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="http://10.0.159.3:8080/web/meinv2.jpg"
android:id="@+id/imagepath"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/button"
android:id="@+id/button"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageview" />
</LinearLayout>
二:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/imagebutton"
android:id="@+id/imagebutton"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/openotheractivtiybutton"
android:id="@+id/openotheractivtiybutton"
android:onClick="openOterProcess"/>
</LinearLayout>
Androidmainfest.xml配置:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.netimage"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".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>
<activity
android:name=".NetImageActivity">
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
網絡源碼查看器:
package com.example.service;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.util.Log;
import com.example.utils.StreamTool;
public class pageService {
public static String getHtml(String path) throws Exception{
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode() == 200)
{
InputStream in=conn.getInputStream();
byte[] data=StreamTool.read(in);
return new String(data,"utf-8");
}
return null;
}
}
和網絡圖片查看器的實現類似,只是獲得數據的格式有些不一樣。
下面是查看源碼的按鈕處理事件函數:
public void htmlView(View v)
{
String path=pathText.getText().toString();
try{
String html=pageService.getHtml(path);
codeText.setText(html);
}catch(Exception e){
e.printStackTrace();
Toast.makeText(this.getApplicationContext(),R.string.gethtmlfaied,1).show();
}
}
經常會遇到.getResponseCode()拋出異常或者無響應的情況,原因可能是網絡問題,或者是這些操作應該放在子線程正實現。我碰到是通過上面方法解決的。有同樣問題且上面方法解決不了的可以一起討論。