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) { //2、下载暂停 downloadInfo.currentState = STATE_PAUSED; notifyDownloadStateChanged(downloadInfo); } else { //1、下载失败 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.java
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.java
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.java
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() { //1、获取当前线程的id int currentThreadId = android.os.Process.myTid(); //2、获取主线程的id int mainThreadId = getMainThreadId(); //3、做比较 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; /** * 1、生命周期长 * 2、单实例 * 3、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维护的是主线程消息队列的方式:1、2、 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
时间: 2024-10-06 15:20:00