下载管理器类的封装(观察者模式)

DownloadManager:

package com.study.googleplay.manager;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import android.content.Intent;
import android.net.Uri;

import com.study.googleplay.db.dao.DownloadInfoDao;
import com.study.googleplay.domain.AppInfo;
import com.study.googleplay.domain.DownloadInfo;
import com.study.googleplay.http.HttpHelper;
import com.study.googleplay.http.HttpHelper.HttpResult;
import com.study.googleplay.utils.IOUtils;
import com.study.googleplay.utils.LogUtils;
import com.study.googleplay.utils.UIUtils;

/**
 * 下载管理器
 * 
 * 
 * -未下载-等待下载-正在下载-暂停下载-下载失败-下载成功-
 * 
 * DownloadManager:被观察者,有责任通知所有的观察者状态和进度发生变化
 * 
 * 
 * 为了增强用户体验,加了数据库,存储每一次下载的文件信息,
 * 同时根据信息回显状态,下次再下载时端点续传。
 * 
 * @author TCL
 * @date 2016-6-13
 */
public class DownloadManager {

	private static DownloadManager downloadManager;

	public static final int STATE_UNDO = 0;
	public static final int STATE_WAITTING = 1;
	public static final int STATE_DOWNLOADING = 2;
	public static final int STATE_PAUSE = 3;
	public static final int STATE_ERROR = 4;
	public static final int STATE_SUCCESS = 5;

	// 4.观察者集合
	private List observers = 
			new ArrayList();

	// 下载队列
	private ConcurrentHashMap downloadInfoMap = 
			new ConcurrentHashMap();

	// 下载任务的集合
	private ConcurrentHashMap downloadTaskMap = 
			new ConcurrentHashMap();

	private DownloadManager() {

	}

	public static DownloadManager getInstance() {
		if (downloadManager == null) {
			synchronized (DownloadManager.class) {
				if (downloadManager == null) {
					downloadManager = new DownloadManager();
				}
			}
		}
		return downloadManager;
	}

	/**
	 * 1.声明观察者接口
	 * 
	 * @author TCL
	 * @date 2016-6-13
	 */
	public interface DownloadObserver {
		// 下载状态发生变化
		public void onDownloadStateChanged(DownloadInfo downloadInfo);

		// 下载进度发生变化
		public void onDownloadProgressChanged(DownloadInfo downloadInfo);
	}

	// 2.注册观察者
	public void registerObserver(DownloadObserver observer) {
		if (observer != null && !observers.contains(observer)) {
			observers.add(observer);
		}
	}

	// 3.注销观察者
	public void unregisterObserver(DownloadObserver observer) {
		if (observer != null && observers.contains(observer)) {
			observers.remove(observer);
		}
	}

	// 5.通知下载状态发生变化
	public void notifyDownloadStateChanged(DownloadInfo downloadInfo) {
		for (DownloadObserver observer : observers) {
			observer.onDownloadStateChanged(downloadInfo);
		}
	}

	// 6.通知下载进度发生变化
	public void notifyDownloadProgressChanged(DownloadInfo downloadInfo) {
		for (DownloadObserver observer : observers) {
			observer.onDownloadProgressChanged(downloadInfo);
		}
	}

	// 下载的方法
	public synchronized void download(AppInfo appInfo) {
		// 如果对象是第一次下载的话,要创建一个新的DownloadInfo对象,重头下载
		// 如果之前下载过,要从数据库读取数据,接着下载,实现断点续传

		DownloadInfo downloadInfo = DownloadInfoDao.getInstance()
				.getDownloadInfo(appInfo.id);

		if (downloadInfo == null) {
			downloadInfo = DownloadInfo.copy(appInfo);
		} 
//		else {
//			downloadInfo.id = appInfo.id;
//		}
		LogUtils.i("download?name=" + downloadInfo.downloadUrl);

		downloadInfo.currentState = STATE_WAITTING;// 状态切换
		notifyDownloadStateChanged(downloadInfo);// 通知所有的观察者,状态发生变化了

		// 将下载对象放入下载队列集合
		downloadInfoMap.put(downloadInfo.id, downloadInfo);

		// 请求网络下载
		DownloadTask downloadTask = new DownloadTask(downloadInfo);
		ThreadManager.getInstance().execute(downloadTask);

		// 将下载任务放入集合中
		downloadTaskMap.put(downloadInfo.id, downloadTask);

	}

	class DownloadTask implements Runnable {
		private DownloadInfo downloadInfo;
		private HttpResult httpResult;

		public DownloadTask(DownloadInfo downloadInfo) {
			this.downloadInfo = downloadInfo;
		}

		@Override
		public void run() {

			// 状态切换
			downloadInfo.currentState = STATE_DOWNLOADING;
			notifyDownloadStateChanged(downloadInfo);

			File file = new File(downloadInfo.path);

			if (!file.exists() || file.length() != downloadInfo.currentPos
					|| downloadInfo.currentPos == 0) {
				// 从头下载
				// 删除无效文件
				file.delete();// 文件不存在也是可以调用这个方法的,不报错
				downloadInfo.currentPos = 0;// 当前下载0

				LogUtils.i(HttpHelper.URL + "download?name="
						+ downloadInfo.downloadUrl);
				httpResult = HttpHelper.download(HttpHelper.URL
						+ "download?name=" + downloadInfo.downloadUrl);// 从头开始下载文件
			} else {
				// 断点续传
				// range表示服务器从文件的哪个位置开始返回数据
				httpResult = HttpHelper.download(HttpHelper.URL
						+ "download?name=" + downloadInfo.downloadUrl
						+ "&range=" + file.length());

			}
			if (httpResult != null && httpResult.getInputStream() != null) {
				InputStream inputStream = httpResult.getInputStream();
				BufferedOutputStream outputStream = null;
				try {
					outputStream = new BufferedOutputStream(
							new FileOutputStream(file, true));// 要在原文件追加

					int len = 0;
					byte[] buffer = new byte[1024];
					// 只有状态正在下载,才循环,解决下载中途暂停的问题
					while ((len = inputStream.read(buffer)) != -1
							&& downloadInfo.currentState == STATE_DOWNLOADING) {// 还要判断当前是否正在下载的状态
						outputStream.write(buffer, 0, len);
						outputStream.flush();

						// 更新下载进度
						downloadInfo.currentPos += len;
						notifyDownloadProgressChanged(downloadInfo);
					}

				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					IOUtils.close(inputStream);
					IOUtils.close(outputStream);
				}
				// 文件下载结束,可能不成功
				if (file.length() == downloadInfo.size) {
					// 表示下载成功
					downloadInfo.currentState = STATE_SUCCESS;
					notifyDownloadStateChanged(downloadInfo);
					// install(downloadInfo);// 安装

					// 将下载大小,等信息存到数据库,以便于下次进入应用回显信息
					DownloadInfoDao.getInstance()
							.saveDownloadInfo(downloadInfo);

				} else if (downloadInfo.currentState == STATE_PAUSE) {// 中途暂停

					// 暂停时信息存储
					DownloadInfoDao.getInstance()
							.saveDownloadInfo(downloadInfo);
					notifyDownloadStateChanged(downloadInfo);
				} else {
					// 下载失败
					downloadInfo.currentState = STATE_ERROR;// 下载失败
					downloadInfo.currentPos = 0;
					notifyDownloadStateChanged(downloadInfo);
					file.delete();// 删除无效文件
				}
			} else {
				// 网络异常
				downloadInfo.currentState = STATE_ERROR;// 下载失败
				downloadInfo.currentPos = 0;
				notifyDownloadStateChanged(downloadInfo);
				file.delete();// 删除无效文件
			}

			// 从集合中移除下载任务
			downloadTaskMap.remove(downloadInfo.id);
		}
	}

	// 暂停的方法
	public synchronized void pause(AppInfo appInfo) {
		DownloadInfo downloadInfo = downloadInfoMap.get(appInfo.id);
		if (downloadInfo != null) {
			// 只有在正在下载和等待下载时才暂停
			if (downloadInfo.currentState == STATE_DOWNLOADING
					|| downloadInfo.currentState == STATE_WAITTING) {
				DownloadTask task = downloadTaskMap.get(downloadInfo.id);
				if (task != null) {
					ThreadManager.getInstance().cancel(task);
				}
				downloadInfo.currentState = STATE_PAUSE;// 状态切换
				notifyDownloadStateChanged(downloadInfo);// 通知切换
				// 暂停时把数据写到数据库
				DownloadInfoDao.getInstance().saveDownloadInfo(downloadInfo);
			}
		}
	}

	// 安装的方法
	public synchronized void install(DownloadInfo downloadInfo) {
		// 跳到系统的安装页面进行安装
		if (downloadInfo != null) {
			Intent intent = new Intent(Intent.ACTION_VIEW);
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

			LogUtils.e(downloadInfo.path + "---------");
			intent.setDataAndType(Uri.parse("file://" + downloadInfo.path),
					"application/vnd.android.package-archive");
			UIUtils.getContext().startActivity(intent);
		}

	}
}

ThreadManager:

package com.study.googleplay.manager;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
import java.util.concurrent.TimeUnit;

public class ThreadManager {

	/**
	 * 线程池
	 * 
	 * @author TCL
	 * @date 2016-6-13
	 */
	private static ThreadPool threadPoolpool;

	public static ThreadPool getInstance() {
		if (threadPoolpool == null) {
			synchronized (ThreadManager.class) {
				if (threadPoolpool == null) {
					int threadCount = Runtime.getRuntime()
							.availableProcessors() * 2 + 1;// 线程个数
					threadPoolpool = new ThreadPool(threadCount, threadCount,
							1L);
				}
			}
		}
		return threadPoolpool;
	}

	public static class ThreadPool {
		private int corePoolSize;// 核心线程数
		private int maximumPoolSize;// 最大线程数
		private long keepAliveTime;// 休息时间
		private ThreadPoolExecutor executor;

		private ThreadPool(int corePoolSize, int maximumPoolSize,
				long keepAliveTime) {
			this.corePoolSize = corePoolSize;
			this.maximumPoolSize = maximumPoolSize;
			this.keepAliveTime = keepAliveTime;

		}

		public void execute(Runnable r) {
			// 参数1:核心线程数,参数2:最大线程数,参数3:休息时间,参数4:时间单位,
			// 参数5:线程队列参数6:生产线程的工厂,参数7:线程异常策略
			if (executor == null) {
				executor = new ThreadPoolExecutor(corePoolSize,
						maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,
						new LinkedBlockingDeque(),
						Executors.defaultThreadFactory(), new AbortPolicy());
			}
			executor.execute(r);// 执行一个Runnable对象,具体执行时机由线程池说了算
		}

		// 取消任务
		public void cancel(Runnable r) {
			if (r != null) {
				// 如果任务还没开始,正在等待,可以通过 此方法移除,
				// 如果任务已经开始,需要在run方法中进行中断
				executor.getQueue().remove(r);// 从线程池中移除对象
			}
		}
	}
}
Http的封装(HttpHelper):

package com.study.googleplay.http;

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 com.study.googleplay.utils.IOUtils;
import com.study.googleplay.utils.LogUtils;
import com.study.googleplay.utils.StringUtils;

public class HttpHelper {

	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);// 把错误异常交给重试机制,以判断是否需要采取从事
				LogUtils.e(e);
			}
		}
		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) {
					LogUtils.e(e);
				} finally {
					IOUtils.close(out);
					close();
				}
			}
			return mStr;
		}

		/** 获取流,需要使用完毕后调用close方法关闭网络连接 */
		public InputStream getInputStream() {
			LogUtils.i("--------------------"+getCode());
			if (mIn == null && getCode() < 300) {
				HttpEntity entity = mResponse.getEntity();
				try {
					mIn = entity.getContent();
				} catch (Exception e) {
					LogUtils.e(e);
				}
			}
			return mIn;
		}

		/** 关闭网络连接 */
		public void close() {
			if (mRequestBase != null) {
				mRequestBase.abort();
			}
			IOUtils.close(mIn);
			if (mHttpClient != null) {
				mHttpClient.getConnectionManager().closeExpiredConnections();
			}
		}
	}
}

下载信息的封装(DownloadInfo):

package com.study.googleplay.domain;

import java.io.File;

import android.os.Environment;

import com.study.googleplay.manager.DownloadManager;

/**
 * 下载对象  
 * 
 * @author TCL
 * @date 2016-6-13
 */
public class DownloadInfo {

	public String id;// 下载id
	public String name;// 下载名称
	public String downloadUrl;// 下载链接
	public String packageName;// 包名
	public long size;// 大小

	public long currentPos;// 当前下载位置
	public int currentState;// 当前下载状态

	public String path;// 下载到本地的路径

	public static final String GOOGLE_MARKET = "googlemarket";// sdcard跟目录文件夹名
	public static final String DOWNLOAD = "download";// 子文件夹名称,存放下载的文件

	// 获取下载进度(0-1)
	public float getProgress() {
		if (size == 0) {
			return 0;
		}
		return currentPos / (float) size;
	}

	// copy对象,从app对象中拷贝出一个DownloadInfo
	public static DownloadInfo copy(AppInfo appInfo) {
		DownloadInfo downloadInfo = new DownloadInfo();
		downloadInfo.name = appInfo.name;
		downloadInfo.id = appInfo.id;
		downloadInfo.packageName = appInfo.packageName;
		downloadInfo.size = appInfo.size;

		downloadInfo.currentPos = 0;
		downloadInfo.currentState = DownloadManager.STATE_UNDO;

		downloadInfo.path = downloadInfo.getFilePath();

		return downloadInfo;

	}

	// 获取文件下载后存放路径
	public String getFilePath() {
		StringBuilder sb = new StringBuilder();
		String sdcard = Environment.getExternalStorageDirectory()
				.getAbsolutePath();
		sb.append(sdcard);
		sb.append(File.separator);
		sb.append(GOOGLE_MARKET);
		sb.append(File.separator);
		sb.append(DOWNLOAD);

		if (createDir(sb.toString())) {
			return sb.toString() + File.separator + name + ".apk";
		}
		return null;
	}

	public boolean createDir(String dir) {
		File dirFile = new File(dir);
		if (!dirFile.exists() || !dirFile.isDirectory()) {// 文件夹不存在或者不是一个文件夹
			return dirFile.mkdirs();
		}
		return true;// 文件夹存在
	}

}


DownloadInfoDao:

package com.study.googleplay.db.dao;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.study.googleplay.db.DownloadInfoOpenHelper;
import com.study.googleplay.domain.DownloadInfo;
import com.study.googleplay.utils.UIUtils;

/**
 * 数据库访问类
 * 
 * @author TCL
 * @date 2016-6-14
 */

public class DownloadInfoDao {

	private static DownloadInfoDao downloadInfoDao;
	private DownloadInfoOpenHelper downloadInfoOpenHelper;

	private DownloadInfoDao() {
		downloadInfoOpenHelper = new DownloadInfoOpenHelper(
				UIUtils.getContext());
	}

	public static DownloadInfoDao getInstance() {
		if (downloadInfoDao == null) {
			synchronized (DownloadInfoDao.class) {
				if (downloadInfoDao == null) {
					downloadInfoDao = new DownloadInfoDao();
				}
			}
		}
		return downloadInfoDao;
	}

	// 保存下载信息
	public boolean saveDownloadInfo(DownloadInfo downloadInfo) {
		SQLiteDatabase database = downloadInfoOpenHelper.getWritableDatabase();
		ContentValues values = new ContentValues();
		if (downloadInfo != null) {
			values.put("id", downloadInfo.id);
			values.put("name", downloadInfo.name);
			values.put("currentPos", downloadInfo.currentPos);
			values.put("path", downloadInfo.path);
			values.put("downloadUrl", downloadInfo.downloadUrl);
			values.put("size", downloadInfo.size);

			if (getDownloadInfo(downloadInfo.id) == null) {// 判断数据库是否已经存过
				database.insert("downloadInfo", null, values);
			} else {
				database.update("downloadInfo", values, "id = ?",
						new String[] { downloadInfo.id });
			}
			return true;
		}
		return false;
	}

	// 得到下载信息
	public DownloadInfo getDownloadInfo(String id) {
		SQLiteDatabase database = downloadInfoOpenHelper.getReadableDatabase();
		DownloadInfo downloadInfo = null;
		Cursor cursor = database.query("downloadInfo", null, "id = ? ",
				new String[] { id }, null, null, null);
		if (cursor.moveToNext()) {
			downloadInfo = new DownloadInfo();
			downloadInfo.id = id;
			downloadInfo.currentPos = cursor.getLong(cursor
					.getColumnIndex("currentPos"));
			downloadInfo.name = cursor.getString(cursor.getColumnIndex("name"));
			downloadInfo.path = cursor.getString(cursor.getColumnIndex("path"));
			downloadInfo.downloadUrl = cursor.getString(cursor
					.getColumnIndex("downloadUrl"));
			downloadInfo.size = cursor.getLong(cursor.getColumnIndex("size"));
		}
		return downloadInfo;
	}
}

DownloadInfoOpenHelper:

package com.study.googleplay.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * 存储下载信息的数据库
 * 
 * @author TCL
 * @date 2016-6-14
 */
public class DownloadInfoOpenHelper extends SQLiteOpenHelper {

	public DownloadInfoOpenHelper(Context context) {
		super(context, "downloadInfoDb", null, 1);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("create table downloadInfo(id varchar(20),"
				+ "name varchar(20),currentPos number,"
				+ "path varchar(50),downloadUrl varchar(50),size number)");
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

	}

}


IOUtils:

package com.study.googleplay.utils;

import java.io.Closeable;
import java.io.IOException;

public class IOUtils {
	/** 关闭流 */
	public static boolean close(Closeable io) {
		if (io != null) {
			try {
				io.close();
			} catch (IOException e) {
				LogUtils.e(e);
			}
		}
		return true;
	}
}

LogUtils:

package com.study.googleplay.utils;

import android.util.Log;

public class LogUtils {
	/** 日志输出级别NONE */
	public static final int LEVEL_NONE = 0;
	/** 日志输出级别E */
	public static final int LEVEL_ERROR = 1;
	/** 日志输出级别W */
	public static final int LEVEL_WARN = 2;
	/** 日志输出级别I */
	public static final int LEVEL_INFO = 3;
	/** 日志输出级别D */
	public static final int LEVEL_DEBUG = 4;
	/** 日志输出级别V */
	public static final int LEVEL_VERBOSE = 5;

	/** 日志输出时的TAG */
	private static String mTag = "LogUtils";
	/** 是否允许输出log */
	private static int mDebuggable = LEVEL_VERBOSE;

	/** 以级别为 d 的形式输出LOG */
	public static void v(String msg) {
		if (mDebuggable >= LEVEL_VERBOSE) {
			Log.v(mTag, msg);
		}
	}

	/** 以级别为 d 的形式输出LOG */
	public static void d(String msg) {
		if (mDebuggable >= LEVEL_DEBUG) {
			Log.d(mTag, msg);
		}
	}

	/** 以级别为 i 的形式输出LOG */
	public static void i(String msg) {
		if (mDebuggable >= LEVEL_INFO) {
			Log.i(mTag, msg);
		}
	}

	/** 以级别为 w 的形式输出LOG */
	public static void w(String msg) {
		if (mDebuggable >= LEVEL_WARN) {
			Log.w(mTag, msg);
		}
	}

	/** 以级别为 w 的形式输出Throwable */
	public static void w(Throwable tr) {
		if (mDebuggable >= LEVEL_WARN) {
			Log.w(mTag, "", tr);
		}
	}

	/** 以级别为 w 的形式输出LOG信息和Throwable */
	public static void w(String msg, Throwable tr) {
		if (mDebuggable >= LEVEL_WARN && null != msg) {
			Log.w(mTag, msg, tr);
		}
	}

	/** 以级别为 e 的形式输出LOG */
	public static void e(String msg) {
		if (mDebuggable >= LEVEL_ERROR) {
			Log.e(mTag, msg);
		}
	}

	/** 以级别为 e 的形式输出Throwable */
	public static void e(Throwable tr) {
		if (mDebuggable >= LEVEL_ERROR) {
			Log.e(mTag, "", tr);
		}
	}

	/** 以级别为 e 的形式输出LOG信息和Throwable */
	public static void e(String msg, Throwable tr) {
		if (mDebuggable >= LEVEL_ERROR && null != msg) {
			Log.e(mTag, msg, tr);
		}
	}
}
StringUtils:

package com.study.googleplay.utils;

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;
		}
	}
}


你可能感兴趣的:(【Android】)