package com.hit.changyou; import android.app.Activity; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.kobjects.base64.Base64; import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.HttpTransportSE; import org.xmlpull.v1.XmlPullParserException; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.StatFs; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; public class ARDetailActivity extends Activity { private static final String TAG="ARDetailActivity"; protected static final int TASK_DONE = 0; protected static final int TASK_CANCEL = 1; protected static final int TASK_UNDONE = 2; Handler handle; String id=null; private ImageView iv; private TextView tv_desc; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.ardetail); id = this.getIntent().getExtras().getString("ID"); String name = this.getIntent().getExtras().getString("NAME"); String desc = this.getIntent().getExtras().getString("DESC"); ((TextView) this.findViewById(R.id.tv_Name)).setText(name); tv_desc=((TextView) this.findViewById(R.id.tv_Desc)); tv_desc.setText(desc); tv_desc.setMovementMethod(ScrollingMovementMethod.getInstance()); iv=(ImageView) findViewById(R.id.iv); /*如果可用空间小于500KB,那么提示用户空间不足*/ if(getAvailaleSize()<500){ Toast lowStorageToast=Toast.makeText(this, "检测到您手机的存储空间不足,所以不进行图片缓存(这样每次加载图片时会耗费一些流量)", Toast.LENGTH_LONG); lowStorageToast.show(); } wsAsyncTask wsTask = new wsAsyncTask(this); wsTask.execute(id); handle=new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch(msg.what){ case TASK_DONE: Log.v(TAG, "task is done"); iv.setImageBitmap((Bitmap)msg.obj); // ((Bitmap)msg.obj).recycle(); /* * 不加这句已经运行正常,加上后会异常终止,因为在这里 *释放它太早了,log显示此时Canvas还在使用它 */ break; case TASK_CANCEL: Log.v(TAG, "task is cancelled"); iv.setImageResource(R.drawable.defaultimg); break; case TASK_UNDONE: Log.v(TAG, "task is undone"); break; } } }; } /*获取外部存储可用空间*/ public static long getAvailaleSize(){ File path = Environment.getExternalStorageDirectory(); StatFs stat = new StatFs(path.getPath()); long blockSize = stat.getBlockSize(); long availableBlocks = stat.getAvailableBlocks(); return (availableBlocks * blockSize)/1024; //以KIB 单位 //(availableBlocks * blockSize)/1024 /1024 MIB单位 } /* * 这个函数会对图片的大小进行判断,并得到合适的缩放比例,比如2即1/2,3即1/3 */ static int computeSampleSize(BitmapFactory.Options options, int tarWidth, int tarHeight) { int realWidth = options.outWidth; int realHeight = options.outHeight; int candidateW = realWidth / tarWidth; int candidateH = realHeight / tarHeight; int candidate = Math.max(candidateW, candidateH); if (candidate == 0){ Log.v(TAG, "realWidth:"+realWidth+" realHeight:" + realHeight + " return " + candidate); return 1; } /*以下部分是为了防止这种情况:如果width或height只有一个特别大,另一个与real值接近,那么得到的candidate * 值是不准确,是过大的,所以要调整,适当将其减一*/ if (candidate > 1) { if ((realWidth > tarWidth) && (realWidth / candidate) < tarWidth) candidate -= 1; } if (candidate > 1) { if ((realHeight > tarHeight) && (realHeight / candidate) < tarHeight) candidate -= 1; } Log.v(TAG, "realWidth:"+realWidth+" realHeight:" + realHeight + " return " + candidate); return candidate; } private class wsAsyncTask extends AsyncTask<String, Integer, Bitmap> { //应用在sd卡上的图片保存目录 String dir=Environment.getExternalStorageDirectory()+"/ARNavigator/images"; File mydir=null; File file=null; private Toast toast; private Bitmap img=null; private Drawable drawable=null; private ProgressDialog progress; /* * 检查某图片是否已经在sdcard存在的方法 */ boolean checkIfExist(String param){ mydir=new File(dir); Log.v(TAG, "mydir is "+dir); if(mydir.exists()){ Log.v(TAG, "mydir exists!"); file=new File(mydir, param+".jpg"); if(file.exists()){ Log.v(TAG, "file exists!"); drawable = Drawable.createFromPath(dir+"/"+param+".jpg"); if(drawable!=null){ Log.v(TAG, "drawable is not null!"); return true; } else{ Log.v(TAG, "drawable is null!"); return false; } } } return false; } /* * 保存图片到sd卡 */ void saveToSD(String param){ boolean tag_save=false; if(!mydir.exists()){ if(!mydir.mkdirs()){ Log.v(TAG, "Cannot create the dir!"); } else tag_save=true; } else{ tag_save=true; } /*如果可用空间小于500KB,则不进行缓存*/ if(getAvailaleSize()<500){ tag_save=false; } if(tag_save==true){ //目录已经建好或已经存在 File file=new File(mydir, param+".jpg"); FileOutputStream fos; try { fos = new FileOutputStream(file); img.compress(Bitmap.CompressFormat.JPEG, 100, fos); Log.v(TAG, "save image to sdcard!"); fos.flush(); fos.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public wsAsyncTask(Context context){ progress=new ProgressDialog(context); progress.setProgressStyle(ProgressDialog.STYLE_SPINNER); progress.setIndeterminate(false); progress.setCancelable(true); // progress.setCanceledOnTouchOutside(true); //设置是否可以点击屏幕停止加载,这样容易误操作,所以不用了 progress.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // TODO Auto-generated method stub toast.setText("已取消图片加载"); toast.show(); wsAsyncTask.this.cancel(true); } }); progress.setMessage("图片加载中..."); progress.show(); toast=Toast.makeText(context, "按返回键可取消图片加载(如果您的网络状况很差)", Toast.LENGTH_LONG); } @Override protected Bitmap doInBackground(String... params) { // TODO Auto-generated method stub if((checkIfExist(params[0]))==true){ img=((BitmapDrawable)drawable).getBitmap(); return img; } toast.show(); Log.v(TAG, "load img from web service!"); /* * 用虚拟器运行时,IP可以是电脑的真实IP或者10.0.2.2;用真机运行时,要用真实IP而且与电脑要在同一个网段 * 127.0.0.1和local host代表虚拟器本身 */ // String wsUrl="http://10.0.2.2:8080/axis2/services/picTransport?wsdl"; // String wsUrl="http://192.168.1.103:8080/axis2/services/picTransport?wsdl"; // String wsUrl="http://192.168.44.1:8080/axis2/services/picTransport?wsdl"; String wsUrl="http://photo.hit.edu.cn/axis2/services/picTransport?wsdl"; String wsNamespace="http://ws.apache.org/axis2"; String wsMethodname="fileDownload"; SoapObject request=new SoapObject(wsNamespace, wsMethodname); request.addProperty("id", params[0]); SoapSerializationEnvelope envelop=new SoapSerializationEnvelope(SoapEnvelope.VER11); envelop.bodyOut=request; HttpTransportSE ht=new HttpTransportSE(wsUrl); try { ht.call(null, envelop); if(envelop.getResponse()!=null){ Object result=envelop.getResponse(); byte[] buffer=Base64.decode(result.toString()); BitmapFactory.Options options=new Options(); options.inJustDecodeBounds = true; //调用此方法得到options得到图片的大小 BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options); //我的目标是在大约400*480 pixel的画面上显示,所以调用computeSampleSize得到图片缩放的比例 options.inSampleSize = computeSampleSize(options, 480, 400); //OK,得到了缩放的比例,现在开始正式读入BitMap数据 options.inJustDecodeBounds = false; options.inDither=false; /*不进行图片抖动处理*/ options.inPreferredConfig=null; /*设置让解码器以最佳方式解码*/ img=BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options); saveToSD(params[0]); try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return img; } else{} } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap result) { // TODO Auto-generated method stub super.onPostExecute(result); Log.v(TAG, "in on postExcute!"); progress.dismiss(); toast.cancel(); if(result!=null){ Message message=handle.obtainMessage(); message.what=TASK_DONE; message.obj=result; message.sendToTarget(); } else{ Message message=handle.obtainMessage(); message.what=TASK_UNDONE; message.sendToTarget(); } } @Override protected void onCancelled() { // TODO Auto-generated method stub super.onCancelled(); Log.v(TAG, "task is cancelled!"); Message message=handle.obtainMessage(); message.what=TASK_CANCEL; message.sendToTarget(); } } }