import android.content.Intent; import android.net.Uri; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; /** * 下載的管理類 */ public class MyDownloadManager { public static final int STATE_NONE = 0;//未下載 public static final int STATE_WAITING = 1;//等待中 public static final int STATE_DOWNLOADING= 2;//下載中 public static final int STATE_PAUSED= 3;//下載暫停 public static final int STATE_SUCCESS = 4;//下載成功 public static final int STATE_ERROR = 5;//下載失敗 private MyDownloadManager() {} private static MyDownloadManager instance; public synchronized static MyDownloadManager getInstance() { if (instance == null) { instance = new MyDownloadManager(); } return instance; } public HashMap<String, DownloadInfo> mSavedDownloadInfo = new HashMap<>(); public HashMap<String, DownloadTask> mSavedDownloadTask = new HashMap<>(); //對於AppInfo來講,downloadUrl、size、id、name、packageName //存在本地的路徑,當前下載的狀態,當前下載的進度 public void startDownload(AppInfo info) { //須要將downloadInfo緩存起來,以便咱們繼續下載的時候來使用 DownloadInfo downloadInfo = mSavedDownloadInfo.get(info.id);//DownloadInfo.createDownloadInfoFromAppInfo(info); if(downloadInfo == null) { downloadInfo = DownloadInfo.createDownloadInfoFromAppInfo(info); mSavedDownloadInfo.put(info.id, downloadInfo); } //開始真正的下載了 DownloadTask task = new DownloadTask(downloadInfo); mSavedDownloadTask.put(info.id, task); downloadInfo.currentState = MyDownloadManager.STATE_WAITING; notifyDownloadStateChanged(downloadInfo); MyThreadPoolManager.getInstance().execute(task); } public void pauseDownload(AppInfo data) { //暫停下載 DownloadInfo downloadInfo = mSavedDownloadInfo.get(data.id); downloadInfo.currentState = STATE_PAUSED; //若是有一個任務已經丟到了線程池中,可是run方法尚未執行 //將任務從等待區域中移除 DownloadTask task = mSavedDownloadTask.get(data.id); MyThreadPoolManager.getInstance().cancle(task); } public void installApk(AppInfo data) { DownloadInfo downloadInfo = mSavedDownloadInfo.get(data.id); //打開系統的安裝界面 Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType( Uri.fromFile(new File(downloadInfo.filePath)), "application/vnd.android.package-archive"); UiUtils.getContext().startActivity(intent); } class DownloadTask implements Runnable { private DownloadInfo downloadInfo; public DownloadTask(DownloadInfo downloadInfo) { this.downloadInfo = downloadInfo; } @Override public void run() { FileOutputStream fos = null; try { //因爲是由線程池來進行管理的,因此只有走到了run方法才表明這個任務被線程池中的線程執行 downloadInfo.currentState = MyDownloadManager.STATE_DOWNLOADING; notifyDownloadStateChanged(downloadInfo); //區分一下是不是第一次下載 File downloadFile = new File(downloadInfo.filePath); //下載apk String url = ""; if(!downloadFile.exists() ||downloadInfo.currentPosition==0 ||(downloadInfo.currentPosition!=0&&downloadInfo.currentPosition != downloadFile.length())) { //第一次下載 downloadFile.delete(); downloadInfo.currentPosition = 0; url = HttpHelper.URL + "download?name=" + downloadInfo.downloadUrl; } else { //表明的是斷電下載,告訴服務器從這個文件的哪一個位置開始給我吐數據 url = HttpHelper.URL + "download?name=" + downloadInfo.downloadUrl+"&range=" + downloadInfo.currentPosition; } HttpHelper.HttpResult httpResult = HttpHelper.download(url); if(httpResult != null) { //獲取文件的輸入流 InputStream inputStream = httpResult.getInputStream(); if(inputStream != null) { //第二個參數必須傳true,不然的話,就會覆蓋以前已經下載好的那一小部分文件 fos = new FileOutputStream(downloadFile,true); byte[] buffer = new byte[1024];//30 int length = 0; while((length = inputStream.read(buffer)) != -1 && downloadInfo.currentState == STATE_DOWNLOADING) { fos.write(buffer, 0, length); downloadInfo.currentPosition = downloadInfo.currentPosition + length; notifyDownloadProgressChanged(downloadInfo); fos.flush(); } //下載完成 //判斷一下下載是否成功 long serverFileSize = Long.parseLong(downloadInfo.size); long localFileSize = downloadInfo.currentPosition; if(serverFileSize == localFileSize) { //下載成功 downloadInfo.currentState = STATE_SUCCESS; notifyDownloadStateChanged(downloadInfo); } else { if(downloadInfo.currentState == STATE_PAUSED) { //二、下載暫停 downloadInfo.currentState = STATE_PAUSED; notifyDownloadStateChanged(downloadInfo); } else { //一、下載失敗 downloadInfo.currentState = STATE_ERROR; notifyDownloadStateChanged(downloadInfo); } } } else { //此時表明服務器訪問成功,可是服務器找不到你所要下載的文件 //下載失敗 downloadInfo.currentState = STATE_ERROR; notifyDownloadStateChanged(downloadInfo); } } else { //下載失敗 downloadInfo.currentState = STATE_ERROR; notifyDownloadStateChanged(downloadInfo); } } catch (Exception e) { downloadInfo.currentState = STATE_ERROR; notifyDownloadStateChanged(downloadInfo); } finally { IOUtils.close(fos); } } } public interface DownloadObserver{ public void onDownloadStateChanged(DownloadInfo downloadInfo); public void onDownloadProgressChanged(DownloadInfo downloadInfo); } private ArrayList<DownloadObserver> observers = new ArrayList<>(); public void addDownloadObserver(DownloadObserver observer) { if(observer != null && !observers.contains(observer)) { observers.add(observer); } } private void notifyDownloadStateChanged(DownloadInfo downloadInfo) { for(int i=0;i<observers.size();i++) { DownloadObserver downloadObserver = observers.get(i); downloadObserver.onDownloadStateChanged(downloadInfo); } } private void notifyDownloadProgressChanged(DownloadInfo downloadInfo) { for(int i=0;i<observers.size();i++) { DownloadObserver downloadObserver = observers.get(i); downloadObserver.onDownloadProgressChanged(downloadInfo); } } }
DownloadIofo.javajava
import android.os.Environment; import java.io.File; import cn.itcast.googleplay10.manager.MyDownloadManager; public class DownloadInfo { public String downloadUrl; public String id; public String name; public String packageName; public String size; public long currentPosition;//當前下載的位置 public int currentState;//下載的狀態 public String filePath;//下載存儲的本地路徑 public static DownloadInfo createDownloadInfoFromAppInfo(AppInfo appInfo) { DownloadInfo downloadInfo = new DownloadInfo(); downloadInfo.id = appInfo.id; downloadInfo.downloadUrl = appInfo.downloadUrl; downloadInfo.name = appInfo.name; downloadInfo.packageName = appInfo.packageName; downloadInfo.size = appInfo.size; downloadInfo.currentState = MyDownloadManager.STATE_NONE; downloadInfo.currentPosition = 0; downloadInfo.filePath = getFilePath(appInfo.name);// /sdcard/GooglePlay10/xxx.apk return downloadInfo; } public static String getFilePath(String name) { File rootDir = Environment.getExternalStorageDirectory(); File appDir = new File(rootDir, "MyFile"); if(!appDir.exists()||appDir.isFile()) { if(appDir.mkdirs()) { } else { return null; } } File apkFile = new File(appDir, name + ".apk"); return apkFile.getAbsolutePath(); } }
AppInfo.javaandroid
package cn.itcast.googleplay10.bean; import java.io.Serializable; import java.util.ArrayList; public class AppInfo { public String des; public String downloadUrl; public String iconUrl; public String id; public String name; public String packageName; public String size; public String stars; public String author; public String date; public String downloadNum; public ArrayList<SafeInfo> safe; public ArrayList<String> screen; public String version; }
SafeInfo.javaapache
public class SafeInfo { public String safeDes; public String safeDesColor; public String safeDesUrl; public String safeUrl; }
httpHelper.java數組
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.AbstractHttpClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.SyncBasicHttpContext; import android.util.Log; import cn.itcast.googleplay10.utils.IOUtils; import cn.itcast.googleplay10.utils.StringUtils; public class HttpHelper { public static final String TAG = "HttpHelper"; //127.0.0.1---> localhost public static final String URL = "http://127.0.0.1:8090/"; /** get請求,獲取返回字符串內容 */ public static HttpResult get(String url) { HttpGet httpGet = new HttpGet(url); return execute(url, httpGet); } /** post請求,獲取返回字符串內容 */ public static HttpResult post(String url, byte[] bytes) { HttpPost httpPost = new HttpPost(url); ByteArrayEntity byteArrayEntity = new ByteArrayEntity(bytes); httpPost.setEntity(byteArrayEntity); return execute(url, httpPost); } /** 下載 */ public static HttpResult download(String url) { HttpGet httpGet = new HttpGet(url); return execute(url, httpGet); } /** 執行網絡訪問 */ private static HttpResult execute(String url, HttpRequestBase requestBase) { boolean isHttps = url.startsWith("https://");//判斷是否須要採用https AbstractHttpClient httpClient = HttpClientFactory.create(isHttps); HttpContext httpContext = new SyncBasicHttpContext(new BasicHttpContext()); HttpRequestRetryHandler retryHandler = httpClient.getHttpRequestRetryHandler();//獲取重試機制 int retryCount = 0; boolean retry = true; while (retry) { try { HttpResponse response = httpClient.execute(requestBase, httpContext);//訪問網絡 if (response != null) { return new HttpResult(response, httpClient, requestBase); } } catch (Exception e) { IOException ioException = new IOException(e.getMessage()); retry = retryHandler.retryRequest(ioException, ++retryCount, httpContext);//把錯誤異常交給重試機制,以判斷是否須要採起從事 Log.e(TAG,e.getMessage()); } } return null; } /** http的返回結果的封裝,能夠直接從中獲取返回的字符串或者流 */ public static class HttpResult { private HttpResponse mResponse; private InputStream mIn; private String mStr; private HttpClient mHttpClient; private HttpRequestBase mRequestBase; public HttpResult(HttpResponse response, HttpClient httpClient, HttpRequestBase requestBase) { mResponse = response; mHttpClient = httpClient; mRequestBase = requestBase; } public int getCode() { StatusLine status = mResponse.getStatusLine(); return status.getStatusCode(); } /** 從結果中獲取字符串,一旦獲取,會自動關流,而且把字符串保存,方便下次獲取 */ public String getString() { if (!StringUtils.isEmpty(mStr)) { return mStr; } InputStream inputStream = getInputStream(); ByteArrayOutputStream out = null; if (inputStream != null) { try { out = new ByteArrayOutputStream(); byte[] buffer = new byte[1024 * 4]; int len = -1; while ((len = inputStream.read(buffer)) != -1) { out.write(buffer, 0, len); } byte[] data = out.toByteArray(); mStr = new String(data, "utf-8"); } catch (Exception e) { Log.e(TAG,e.getMessage()); } finally { IOUtils.close(out); close(); } } return mStr; } /** 獲取流,須要使用完畢後調用close方法關閉網絡鏈接 */ public InputStream getInputStream() { if (mIn == null && getCode() < 300) { HttpEntity entity = mResponse.getEntity(); try { mIn = entity.getContent(); } catch (Exception e) { Log.e(TAG,e.getMessage()); } } return mIn; } /** 關閉網絡鏈接 */ public void close() { if (mRequestBase != null) { mRequestBase.abort(); } IOUtils.close(mIn); if (mHttpClient != null) { mHttpClient.getConnectionManager().closeExpiredConnections(); } } } }
HttpClientFactory.java緩存
import org.apache.http.*; import org.apache.http.client.params.HttpClientParams; import org.apache.http.conn.params.ConnManagerParams; import org.apache.http.conn.params.ConnPerRouteBean; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.HttpEntityWrapper; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.io.InputStream; import java.net.Socket; import java.net.UnknownHostException; import java.security.*; import java.util.zip.GZIPInputStream; public class HttpClientFactory { /** http請求最大併發鏈接數 */ private static final int MAX_CONNECTIONS = 10; /** 超時時間 */ private static final int TIMEOUT = 10 * 1000; /** 緩存大小 */ private static final int SOCKET_BUFFER_SIZE = 8 * 1024; // 8KB /** 錯誤嘗試次數,錯誤異常表請在RetryHandler添加 */ private static final int MAX_RETRIES = 5; private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; private static final String ENCODING_GZIP = "gzip"; public static DefaultHttpClient create(boolean isHttps) { HttpParams params = createHttpParams(); DefaultHttpClient httpClient = null; if (isHttps) { // 支持http與https SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); // ThreadSafeClientConnManager線程安全管理類 ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); httpClient = new DefaultHttpClient(cm, params); } else { httpClient = new DefaultHttpClient(params); } return httpClient; } private static HttpParams createHttpParams() { final HttpParams params = new BasicHttpParams(); // 設置是否啓用舊鏈接檢查,默認是開啓的。關閉這個舊鏈接檢查能夠提升一點點性能,可是增長了I/O錯誤的風險(當服務端關閉鏈接時)。 // 開啓這個選項則在每次使用老的鏈接以前都會檢查鏈接是否可用,這個耗時大概在15-30ms之間 HttpConnectionParams.setStaleCheckingEnabled(params, false); HttpConnectionParams.setConnectionTimeout(params, TIMEOUT);// 設置連接超時時間 HttpConnectionParams.setSoTimeout(params, TIMEOUT);// 設置socket超時時間 HttpConnectionParams.setSocketBufferSize(params, SOCKET_BUFFER_SIZE);// 設置緩存大小 HttpConnectionParams.setTcpNoDelay(params, true);// 是否不使用延遲發送(true爲不延遲) HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); // 設置協議版本 HttpProtocolParams.setUseExpectContinue(params, true);// 設置異常處理機制 HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);// 設置編碼 HttpClientParams.setRedirecting(params, false);// 設置是否採用重定向 ConnManagerParams.setTimeout(params, TIMEOUT);// 設置超時 ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(MAX_CONNECTIONS));// 多線程最大鏈接數 ConnManagerParams.setMaxTotalConnections(params, 10); // 多線程總鏈接數 return params; } /** 當服務器返回的數據是以Gzip壓縮的事後的數據,填充Response返回的實體數據 (Description),則返回GZIP解壓流 */ private static class InflatingEntity extends HttpEntityWrapper { public InflatingEntity(HttpEntity wrapped) { super(wrapped); } @Override public InputStream getContent() throws IOException { return new GZIPInputStream(wrappedEntity.getContent()); } // 由於數據是壓縮數據,因此實際長度沒法估計,能夠返回-1 @Override public long getContentLength() { return -1; } } /** 自定義的安全套接字協議的實現,目前採用默認的,未使用到 */ private static class SSLSocketFactoryEx extends SSLSocketFactory { // 此類的實例表示安全套接字協議的實現,它充當用於安全套接字工廠或 SSLEngine 的工廠。用可選的一組密鑰和信任管理器及安全隨機字節源初始化此類。 SSLContext sslContext = SSLContext.getInstance("TLS"); public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); // TrustManager負責管理作出信任決定時使用的的信任材料,也負責決定是否接受同位體提供的憑據。 // X509TrustManager此接口的實例管理使用哪個 X509 證書來驗證遠端的安全套接字。決定是根據信任的證書受權、證書撤消列表、在線狀態檢查或其餘方式作出的。 TrustManager tm = new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null;// 返回受驗證同位體信任的認證中心的數組。 } @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { // 給出同位體提供的部分或完整的證書鏈,構建到可信任的根的證書路徑,而且返回是否能夠確認和信任將其用於基於驗證類型的客戶端 SSL 驗證。 } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { // 給出同位體提供的部分或完整的證書鏈,構建到可信任的根的證書路徑,而且返回是否能夠確認和信任將其用於基於驗證類型的服務器 SSL 驗證。 } }; sslContext.init(null, new TrustManager[]{tm}, null); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); } @Override public Socket createSocket() throws IOException { return sslContext.getSocketFactory().createSocket(); } } }
IOutils.java安全
import java.io.Closeable; import java.io.IOException; import android.util.Log; public class IOUtils { public static final String TAG = "IOUtils"; /** 關閉流 */ public static boolean close(Closeable io) { if (io != null) { try { io.close(); } catch (IOException e) { Log.e(TAG, e.getMessage()); } } return true; } }
UiUtils.java服務器
package cn.itcast.googleplay10.utils; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.StateListDrawable; import android.os.Handler; import android.util.DisplayMetrics; import android.view.View; import android.widget.Toast; import java.util.Random; /** * 處理和UI操做相關的工具類 */ public class UiUtils { //獲取全局Context對象 public static Context getContext() { return MyApplication.instance.context; } //獲取主線程的Handler對象 public static Handler getMainThreadHandler() { return MyApplication.instance.handler; } //獲取主線程的線程id public static int getMainThreadId() { return MyApplication.instance.mainThreadId; } //獲取字符串 public static String getString(int resId) { return getContext().getResources().getString(resId); } //獲取字符串數組 public static String[] getStringArray(int resId) { return getContext().getResources().getStringArray(resId); } //獲取drawable public static Drawable getDrawable(int resId) { return getContext().getResources().getDrawable(resId); } public static int getColor(int resId) { return getContext().getResources().getColor(resId); } //產生隨機的顏色值 90~230 public static int getRandomColor() { Random random= new Random(); int red = 90 + random.nextInt(141);; int green= 90 + random.nextInt(141);; int blue= 90 + random.nextInt(141);; int color = Color.rgb(red, green, blue); return color; } //獲取文字大小 16~25 public static int getRandomTextSize() { Random random= new Random(); return 16+random.nextInt(10); } //獲取顏色的狀態選擇器 public static ColorStateList getColorStateList(int resId) { return getContext().getResources().getColorStateList(resId); } public static int getDimen(int resId) { return getContext().getResources().getDimensionPixelSize(resId); } //dip2px public static int dip2px(int dip) { //屏幕密度 float density = getContext().getResources().getDisplayMetrics().density; return (int) (dip * density + 0.5f); } //px2dip public static int px2dip(int px) { //屏幕密度 float density = getContext().getResources().getDisplayMetrics().density; return (int) (px/density + 0.5f); } public static View inflateView(int resId) { return View.inflate(getContext(), resId, null); } public static void toast(String msg) { Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show(); } //判斷是不是在主線程 public static boolean isRunOnUiThread() { //一、獲取當前線程的id int currentThreadId = android.os.Process.myTid(); //二、獲取主線程的id int mainThreadId = getMainThreadId(); //三、作比較 return currentThreadId == mainThreadId; } /** * 保證r這個任務必定是在主線程中執行 * * Process:進程 * Thread:線程 * Runnable:任務 * * @param r */ public static void runOnUiThread(Runnable r) { if (isRunOnUiThread()) { //主線程 //new Thread(r).start(); r.run(); } else { //子線程 getMainThreadHandler().post(r);//將任務r丟到了主線程的消息隊列 } } //代碼中建立shape標籤對應的對象 public static GradientDrawable getShape(int radius,int color) { GradientDrawable gradientDrawable = new GradientDrawable(); gradientDrawable.setShape(GradientDrawable.RECTANGLE); gradientDrawable.setCornerRadius(radius); gradientDrawable.setColor(color); return gradientDrawable; } //代碼中獲取一個狀態選擇器 對應的類StateListDrawable public static StateListDrawable getSelector(Drawable pressedDrawable,Drawable normalDrawable) { StateListDrawable stateListDrawable = new StateListDrawable(); stateListDrawable.addState(new int[]{android.R.attr.state_pressed},pressedDrawable); stateListDrawable.addState(new int[]{},normalDrawable); return stateListDrawable; } public static int getScreenWidth() { DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics(); return displayMetrics.widthPixels; } }
StringUitls.java網絡
public class StringUtils { /** 判斷字符串是否有值,若是爲null或者是空字符串或者只有空格或者爲"null"字符串,則返回true,不然則返回false */ public static boolean isEmpty(String value) { if (value != null && !"".equalsIgnoreCase(value.trim()) && !"null".equalsIgnoreCase(value.trim())) { return false; } else { return true; } //"null" //null } }
MyApplication.java多線程
import android.app.Activity; import android.app.Application; import android.content.Context; import android.os.Handler; import android.os.Looper; import android.os.Process; import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.assist.QueueProcessingType; import java.util.ArrayList; /** * 一、生命週期長 * 二、單實例 * 三、onCreate方法能夠簡單的認爲是一個應用程序的入口,onCreate是運行在主線程中 * * 問題:onCreate這個方法只執行一次麼? * * 注意事項:須要清單文件中註冊 */ public class MyApplication extends Application { public Context context; public Handler handler; public int mainThreadId; public static MyApplication instance; public AppInfo appInfo; @Override public void onCreate() { super.onCreate(); instance = this; //Context 獲取全局的context對象 new出一個View,加載佈局文件,Toast context = getApplicationContext(); //線程間的通訊 //handler.sendMessage:發送一個消息到消息隊列 //主線程有主線程的消息隊列,子線程有子線程的消息隊列 //到底發送到哪個線程的消息隊列,得看handler維護的是哪一個線程的消息隊列 //指定Handler維護的是主線程消息隊列的方式:一、二、 handler = new Handler(); /*new Thread(new Runnable() { @Override public void run() { Handler mHandler = new Handler(Looper.getMainLooper()); } }).start();*/ //判斷當前線程是主線程仍是子線程 mainThreadId = Process.myTid(); initImageLoader(getApplicationContext()); } private ArrayList<Activity> activityArrayList = new ArrayList<>(); public void addActivity(Activity activity) { activityArrayList.add(activity); } public void removeActivity(Activity activity) { activityArrayList.remove(activity); } public static void initImageLoader(Context context) { // This configuration tuning is custom. You can tune every option, you may tune some of them, // or you can create default configuration by // ImageLoaderConfiguration.createDefault(this); // method. ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context); config.threadPriority(Thread.NORM_PRIORITY - 2); config.denyCacheImageMultipleSizesInMemory(); config.diskCacheFileNameGenerator(new Md5FileNameGenerator()); config.diskCacheSize(50 * 1024 * 1024); // 50 MiB config.tasksProcessingOrder(QueueProcessingType.LIFO); config.writeDebugLogs(); // Remove for release app // Initialize ImageLoader with configuration. ImageLoader.getInstance().init(config.build()); } }
導入org.apache.http.legacy.jar併發