localMethodCount = new ThreadLocal<>();
+
+ /**
+ * It is used to determine log settings such as method count, thread info visibility
+ */
+ private final Settings settings = new Settings();
+
+ public LoggerPrinter() {
+ init(DEFAULT_TAG);
+ }
+
+ /**
+ * It is used to change the tag
+ *
+ * @param tag is the given string which will be used in Logger
+ */
+ @Override public Settings init(String tag) {
+ if (tag == null) {
+ throw new NullPointerException("tag may not be null");
+ }
+ if (tag.trim().length() == 0) {
+ throw new IllegalStateException("tag may not be empty");
+ }
+ this.tag = tag;
+ return settings;
+ }
+
+ @Override public Settings getSettings() {
+ return settings;
+ }
+
+ @Override public Printer t(String tag, int methodCount) {
+ if (tag != null) {
+ localTag.set(tag);
+ }
+ localMethodCount.set(methodCount);
+ return this;
+ }
+
+ @Override public void d(String message, Object... args) {
+ log(DEBUG, null, message, args);
+ }
+
+ @Override public void d(Object object) {
+ String message;
+ if (object.getClass().isArray()) {
+ message = Arrays.deepToString((Object[]) object);
+ } else {
+ message = object.toString();
+ }
+ log(DEBUG, null, message);
+ }
+
+ @Override public void e(String message, Object... args) {
+ e(null, message, args);
+ }
+
+ @Override public void e(Throwable throwable, String message, Object... args) {
+ log(ERROR, throwable, message, args);
+ }
+
+ @Override public void w(String message, Object... args) {
+ log(WARN, null, message, args);
+ }
+
+ @Override public void i(String message, Object... args) {
+ log(INFO, null, message, args);
+ }
+
+ @Override public void v(String message, Object... args) {
+ log(VERBOSE, null, message, args);
+ }
+
+ @Override public void wtf(String message, Object... args) {
+ log(ASSERT, null, message, args);
+ }
+
+ /**
+ * Formats the json content and print it
+ *
+ * @param json the json content
+ */
+ @Override public void json(String json) {
+ if (Helper.isEmpty(json)) {
+ d("Empty/Null json content");
+ return;
+ }
+ try {
+ json = json.trim();
+ if (json.startsWith("{")) {
+ JSONObject jsonObject = new JSONObject(json);
+ String message = jsonObject.toString(JSON_INDENT);
+ d(message);
+ return;
+ }
+ if (json.startsWith("[")) {
+ JSONArray jsonArray = new JSONArray(json);
+ String message = jsonArray.toString(JSON_INDENT);
+ d(message);
+ return;
+ }
+ e("Invalid Json");
+ } catch (JSONException e) {
+ e("Invalid Json");
+ }
+ }
+
+ /**
+ * Formats the json content and print it
+ *
+ * @param xml the xml content
+ */
+ @Override public void xml(String xml) {
+ if (Helper.isEmpty(xml)) {
+ d("Empty/Null xml content");
+ return;
+ }
+ try {
+ Source xmlInput = new StreamSource(new StringReader(xml));
+ StreamResult xmlOutput = new StreamResult(new StringWriter());
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+ transformer.transform(xmlInput, xmlOutput);
+ d(xmlOutput.getWriter().toString().replaceFirst(">", ">\n"));
+ } catch (TransformerException e) {
+ e("Invalid xml");
+ }
+ }
+
+ @Override public synchronized void log(int priority, String tag, String message, Throwable throwable) {
+ if (settings.getLogLevel() == LogLevel.NONE) {
+ return;
+ }
+ if (throwable != null && message != null) {
+ message += " : " + Helper.getStackTraceString(throwable);
+ }
+ if (throwable != null && message == null) {
+ message = Helper.getStackTraceString(throwable);
+ }
+ if (message == null) {
+ message = "No message/exception is set";
+ }
+ int methodCount = getMethodCount();
+ if (Helper.isEmpty(message)) {
+ message = "Empty/NULL log message";
+ }
+
+ logTopBorder(priority, tag);
+ logHeaderContent(priority, tag, methodCount);
+
+ //get bytes of message with system's default charset (which is UTF-8 for Android)
+ byte[] bytes = message.getBytes();
+ int length = bytes.length;
+ if (length <= CHUNK_SIZE) {
+ if (methodCount > 0) {
+ logDivider(priority, tag);
+ }
+ logContent(priority, tag, message);
+ logBottomBorder(priority, tag);
+ return;
+ }
+ if (methodCount > 0) {
+ logDivider(priority, tag);
+ }
+ for (int i = 0; i < length; i += CHUNK_SIZE) {
+ int count = Math.min(length - i, CHUNK_SIZE);
+ //create a new String with system's default charset (which is UTF-8 for Android)
+ logContent(priority, tag, new String(bytes, i, count));
+ }
+ logBottomBorder(priority, tag);
+ }
+
+ @Override public void resetSettings() {
+ settings.reset();
+ }
+
+ /**
+ * This method is synchronized in order to avoid messy of logs' order.
+ */
+ private synchronized void log(int priority, Throwable throwable, String msg, Object... args) {
+ if (settings.getLogLevel() == LogLevel.NONE) {
+ return;
+ }
+ String tag = getTag();
+ String message = createMessage(msg, args);
+ log(priority, tag, message, throwable);
+ }
+
+ private void logTopBorder(int logType, String tag) {
+ logChunk(logType, tag, TOP_BORDER);
+ }
+
+ @SuppressWarnings("StringBufferReplaceableByString")
+ private void logHeaderContent(int logType, String tag, int methodCount) {
+ StackTraceElement[] trace = Thread.currentThread().getStackTrace();
+ if (settings.isShowThreadInfo()) {
+ logChunk(logType, tag, HORIZONTAL_DOUBLE_LINE + " Thread: " + Thread.currentThread().getName());
+ logDivider(logType, tag);
+ }
+ String level = "";
+
+ int stackOffset = getStackOffset(trace) + settings.getMethodOffset();
+
+ //corresponding method count with the current stack may exceeds the stack trace. Trims the count
+ if (methodCount + stackOffset > trace.length) {
+ methodCount = trace.length - stackOffset - 1;
+ }
+
+ for (int i = methodCount; i > 0; i--) {
+ int stackIndex = i + stackOffset;
+ if (stackIndex >= trace.length) {
+ continue;
+ }
+ StringBuilder builder = new StringBuilder();
+ builder.append("║ ")
+ .append(level)
+ .append(getSimpleClassName(trace[stackIndex].getClassName()))
+ .append(".")
+ .append(trace[stackIndex].getMethodName())
+ .append(" ")
+ .append(" (")
+ .append(trace[stackIndex].getFileName())
+ .append(":")
+ .append(trace[stackIndex].getLineNumber())
+ .append(")");
+ level += " ";
+ logChunk(logType, tag, builder.toString());
+ }
+ }
+
+ private void logBottomBorder(int logType, String tag) {
+ logChunk(logType, tag, BOTTOM_BORDER);
+ }
+
+ private void logDivider(int logType, String tag) {
+ logChunk(logType, tag, MIDDLE_BORDER);
+ }
+
+ private void logContent(int logType, String tag, String chunk) {
+ String[] lines = chunk.split(System.getProperty("line.separator"));
+ for (String line : lines) {
+ logChunk(logType, tag, HORIZONTAL_DOUBLE_LINE + " " + line);
+ }
+ }
+
+ private void logChunk(int logType, String tag, String chunk) {
+ String finalTag = formatTag(tag);
+ switch (logType) {
+ case ERROR:
+ settings.getLogAdapter().e(finalTag, chunk);
+ break;
+ case INFO:
+ settings.getLogAdapter().i(finalTag, chunk);
+ break;
+ case VERBOSE:
+ settings.getLogAdapter().v(finalTag, chunk);
+ break;
+ case WARN:
+ settings.getLogAdapter().w(finalTag, chunk);
+ break;
+ case ASSERT:
+ settings.getLogAdapter().wtf(finalTag, chunk);
+ break;
+ case DEBUG:
+ // Fall through, log debug by default
+ default:
+ settings.getLogAdapter().d(finalTag, chunk);
+ break;
+ }
+ }
+
+ private String getSimpleClassName(String name) {
+ int lastIndex = name.lastIndexOf(".");
+ return name.substring(lastIndex + 1);
+ }
+
+ private String formatTag(String tag) {
+ if (!Helper.isEmpty(tag) && !Helper.equals(this.tag, tag)) {
+ return this.tag + "-" + tag;
+ }
+ return this.tag;
+ }
+
+ /**
+ * @return the appropriate tag based on local or global
+ */
+ private String getTag() {
+ String tag = localTag.get();
+ if (tag != null) {
+ localTag.remove();
+ return tag;
+ }
+ return this.tag;
+ }
+
+ private String createMessage(String message, Object... args) {
+ return args == null || args.length == 0 ? message : String.format(message, args);
+ }
+
+ private int getMethodCount() {
+ Integer count = localMethodCount.get();
+ int result = settings.getMethodCount();
+ if (count != null) {
+ localMethodCount.remove();
+ result = count;
+ }
+ if (result < 0) {
+ throw new IllegalStateException("methodCount cannot be negative");
+ }
+ return result;
+ }
+
+ /**
+ * Determines the starting index of the stack trace, after method calls made by this class.
+ *
+ * @param trace the stack trace
+ *
+ * @return the stack offset
+ */
+ private int getStackOffset(StackTraceElement[] trace) {
+ for (int i = MIN_STACK_OFFSET; i < trace.length; i++) {
+ StackTraceElement e = trace[i];
+ String name = e.getClassName();
+ if (!name.equals(LoggerPrinter.class.getName()) && !name.equals(Logger.class.getName())) {
+ return --i;
+ }
+ }
+ return -1;
+ }
+
+}
diff --git a/base/src/main/java/com/orhanobut/logger/Printer.java b/base/src/main/java/com/orhanobut/logger/Printer.java
new file mode 100755
index 0000000..a8dce32
--- /dev/null
+++ b/base/src/main/java/com/orhanobut/logger/Printer.java
@@ -0,0 +1,35 @@
+package com.orhanobut.logger;
+
+public interface Printer {
+
+ Printer t(String tag, int methodCount);
+
+ Settings init(String tag);
+
+ Settings getSettings();
+
+ void d(String message, Object... args);
+
+ void d(Object object);
+
+ void e(String message, Object... args);
+
+ void e(Throwable throwable, String message, Object... args);
+
+ void w(String message, Object... args);
+
+ void i(String message, Object... args);
+
+ void v(String message, Object... args);
+
+ void wtf(String message, Object... args);
+
+ void json(String json);
+
+ void xml(String xml);
+
+ void log(int priority, String tag, String message, Throwable throwable);
+
+ void resetSettings();
+
+}
diff --git a/base/src/main/java/com/orhanobut/logger/Settings.java b/base/src/main/java/com/orhanobut/logger/Settings.java
new file mode 100755
index 0000000..2431794
--- /dev/null
+++ b/base/src/main/java/com/orhanobut/logger/Settings.java
@@ -0,0 +1,72 @@
+package com.orhanobut.logger;
+
+public final class Settings {
+
+ private int methodCount = 2;
+ private boolean showThreadInfo = true;
+ private int methodOffset = 0;
+ private LogAdapter logAdapter;
+
+ /**
+ * Determines to how logs will be printed
+ */
+ private LogLevel logLevel = LogLevel.FULL;
+
+ public Settings hideThreadInfo() {
+ showThreadInfo = false;
+ return this;
+ }
+
+ public Settings methodCount(int methodCount) {
+ if (methodCount < 0) {
+ methodCount = 0;
+ }
+ this.methodCount = methodCount;
+ return this;
+ }
+
+ public Settings logLevel(LogLevel logLevel) {
+ this.logLevel = logLevel;
+ return this;
+ }
+
+ public Settings methodOffset(int offset) {
+ this.methodOffset = offset;
+ return this;
+ }
+
+ public Settings logAdapter(LogAdapter logAdapter) {
+ this.logAdapter = logAdapter;
+ return this;
+ }
+
+ public int getMethodCount() {
+ return methodCount;
+ }
+
+ public boolean isShowThreadInfo() {
+ return showThreadInfo;
+ }
+
+ public LogLevel getLogLevel() {
+ return logLevel;
+ }
+
+ public int getMethodOffset() {
+ return methodOffset;
+ }
+
+ public LogAdapter getLogAdapter() {
+ if (logAdapter == null) {
+ logAdapter = new AndroidLogAdapter();
+ }
+ return logAdapter;
+ }
+
+ public void reset() {
+ methodCount = 2;
+ methodOffset = 0;
+ showThreadInfo = true;
+ logLevel = LogLevel.FULL;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/RecycleBin.java b/base/src/main/java/com/wlj/base/RecycleBin.java
new file mode 100755
index 0000000..aaccf3a
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/RecycleBin.java
@@ -0,0 +1,152 @@
+package com.wlj.base;
+
+import android.os.Build;
+import android.util.SparseArray;
+import android.view.View;
+
+/**
+ * The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of
+ * storage: ActiveViews and ScrapViews. ActiveViews are those views which were onscreen at the
+ * start of a layout. By construction, they are displaying current information. At the end of
+ * layout, all views in ActiveViews are demoted to ScrapViews. ScrapViews are old views that
+ * could potentially be used by the adapter to avoid allocating views unnecessarily.
+ *
+ * This class was taken from Android's implementation of {@link android.widget.AbsListView} which
+ * is copyrighted 2006 The Android Open Source Project.
+ */
+public class RecycleBin {
+ /**
+ * Views that were on screen at the start of layout. This array is populated at the start of
+ * layout, and at the end of layout all view in activeViews are moved to scrapViews.
+ * Views in activeViews represent a contiguous range of Views, with position of the first
+ * view store in mFirstActivePosition.
+ */
+ private View[] activeViews = new View[0];
+ private int[] activeViewTypes = new int[0];
+
+ /** Unsorted views that can be used by the adapter as a convert view. */
+ private SparseArray[] scrapViews;
+
+ private int viewTypeCount;
+
+ private SparseArray currentScrapViews;
+
+ public void setViewTypeCount(int viewTypeCount) {
+ if (viewTypeCount < 1) {
+ throw new IllegalArgumentException("Can't have a viewTypeCount < 1");
+ }
+ //noinspection unchecked
+ SparseArray[] scrapViews = new SparseArray[viewTypeCount];
+ for (int i = 0; i < viewTypeCount; i++) {
+ scrapViews[i] = new SparseArray();
+ }
+ this.viewTypeCount = viewTypeCount;
+ currentScrapViews = scrapViews[0];
+ this.scrapViews = scrapViews;
+ }
+
+ protected boolean shouldRecycleViewType(int viewType) {
+ return viewType >= 0;
+ }
+
+ /** @return A view from the ScrapViews collection. These are unordered. */
+ View getScrapView(int position, int viewType) {
+ if (viewTypeCount == 1) {
+ return retrieveFromScrap(currentScrapViews, position);
+ } else if (viewType >= 0 && viewType < scrapViews.length) {
+ return retrieveFromScrap(scrapViews[viewType], position);
+ }
+ return null;
+ }
+
+ /**
+ * Put a view into the ScrapViews list. These views are unordered.
+ *
+ * @param scrap The view to add
+ */
+ void addScrapView(View scrap, int position, int viewType) {
+ if (viewTypeCount == 1) {
+ currentScrapViews.put(position, scrap);
+ } else {
+ scrapViews[viewType].put(position, scrap);
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ scrap.setAccessibilityDelegate(null);
+ }
+ }
+
+ /** Move all views remaining in activeViews to scrapViews. */
+ void scrapActiveViews() {
+ final View[] activeViews = this.activeViews;
+ final int[] activeViewTypes = this.activeViewTypes;
+ final boolean multipleScraps = viewTypeCount > 1;
+
+ SparseArray scrapViews = currentScrapViews;
+ final int count = activeViews.length;
+ for (int i = count - 1; i >= 0; i--) {
+ final View victim = activeViews[i];
+ if (victim != null) {
+ int whichScrap = activeViewTypes[i];
+
+ activeViews[i] = null;
+ activeViewTypes[i] = -1;
+
+ if (!shouldRecycleViewType(whichScrap)) {
+ continue;
+ }
+
+ if (multipleScraps) {
+ scrapViews = this.scrapViews[whichScrap];
+ }
+ scrapViews.put(i, victim);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ victim.setAccessibilityDelegate(null);
+ }
+ }
+ }
+
+ pruneScrapViews();
+ }
+
+ /**
+ * Makes sure that the size of scrapViews does not exceed the size of activeViews.
+ * (This can happen if an adapter does not recycle its views).
+ */
+ private void pruneScrapViews() {
+ final int maxViews = activeViews.length;
+ final int viewTypeCount = this.viewTypeCount;
+ final SparseArray[] scrapViews = this.scrapViews;
+ for (int i = 0; i < viewTypeCount; ++i) {
+ final SparseArray scrapPile = scrapViews[i];
+ int size = scrapPile.size();
+ final int extras = size - maxViews;
+ size--;
+ for (int j = 0; j < extras; j++) {
+ scrapPile.remove(scrapPile.keyAt(size--));
+ }
+ }
+ }
+
+ static View retrieveFromScrap(SparseArray scrapViews, int position) {
+ int size = scrapViews.size();
+ if (size > 0) {
+ // See if we still have a view for this position.
+ for (int i = 0; i < size; i++) {
+ int fromPosition = scrapViews.keyAt(i);
+ View view = scrapViews.get(fromPosition);
+ if (fromPosition == position) {
+ scrapViews.remove(fromPosition);
+ return view;
+ }
+ }
+ int index = size - 1;
+ View r = scrapViews.valueAt(index);
+ scrapViews.remove(scrapViews.keyAt(index));
+ return r;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/RecyclingPagerAdapter.java b/base/src/main/java/com/wlj/base/RecyclingPagerAdapter.java
new file mode 100755
index 0000000..89fb27b
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/RecyclingPagerAdapter.java
@@ -0,0 +1,108 @@
+package com.wlj.base;
+
+import android.support.v4.view.PagerAdapter;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+
+/**
+ * A {@link PagerAdapter} which behaves like an {@link android.widget.Adapter} with view types and
+ * view recycling.
+ */
+public abstract class RecyclingPagerAdapter extends PagerAdapter {
+ static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE;
+
+ private final RecycleBin recycleBin;
+
+ public RecyclingPagerAdapter() {
+ this(new RecycleBin());
+ }
+
+ RecyclingPagerAdapter(RecycleBin recycleBin) {
+ this.recycleBin = recycleBin;
+ recycleBin.setViewTypeCount(getViewTypeCount());
+ }
+
+ @Override public void notifyDataSetChanged() {
+ recycleBin.scrapActiveViews();
+ super.notifyDataSetChanged();
+ }
+
+ @Override public final Object instantiateItem(ViewGroup container, int position) {
+ int viewType = getItemViewType(position);
+ View view = null;
+ if (viewType != IGNORE_ITEM_VIEW_TYPE) {
+ view = recycleBin.getScrapView(position, viewType);
+ }
+ view = getView(position, view, container);
+ container.addView(view);
+ return view;
+ }
+
+ @Override public final void destroyItem(ViewGroup container, int position, Object object) {
+ View view = (View) object;
+ container.removeView(view);
+ int viewType = getItemViewType(position);
+ if (viewType != IGNORE_ITEM_VIEW_TYPE) {
+ recycleBin.addScrapView(view, position, viewType);
+ }
+ }
+
+ @Override public final boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+
+ /**
+ *
+ * Returns the number of types of Views that will be created by
+ * {@link #getView}. Each type represents a set of views that can be
+ * converted in {@link #getView}. If the adapter always returns the same
+ * type of View for all items, this method should return 1.
+ *
+ *
+ * This method will only be called when when the adapter is set on the
+ * the {@link AdapterView}.
+ *
+ *
+ * @return The number of types of Views that will be created by this adapter
+ */
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ /**
+ * Get the type of View that will be created by {@link #getView} for the specified item.
+ *
+ * @param position The position of the item within the adapter's data set whose view type we
+ * want.
+ * @return An integer representing the type of View. Two views should share the same type if one
+ * can be converted to the other in {@link #getView}. Note: Integers must be in the
+ * range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can
+ * also be returned.
+ * @see #IGNORE_ITEM_VIEW_TYPE
+ */
+ @SuppressWarnings("UnusedParameters") // Argument potentially used by subclasses.
+ public int getItemViewType(int position) {
+ return 0;
+ }
+
+ /**
+ * Get a View that displays the data at the specified position in the data set. You can either
+ * create a View manually or inflate it from an XML layout file. When the View is inflated, the
+ * parent View (GridView, ListView...) will apply default layout parameters unless you use
+ * {@link android.view.LayoutInflater#inflate(int, ViewGroup, boolean)}
+ * to specify a root view and to prevent attachment to the root.
+ *
+ * @param position The position of the item within the adapter's data set of the item whose view
+ * we want.
+ * @param convertView The old view to reuse, if possible. Note: You should check that this view
+ * is non-null and of an appropriate type before using. If it is not possible to convert
+ * this view to display the correct data, this method can create a new view.
+ * Heterogeneous lists can specify their number of view types, so that this View is
+ * always of the right type (see {@link #getViewTypeCount()} and
+ * {@link #getItemViewType(int)}).
+ * @param parent The parent that this view will eventually be attached to
+ * @return A View corresponding to the data at the specified position.
+ */
+ public abstract View getView(int position, View convertView, ViewGroup container);
+}
diff --git a/base/src/main/java/com/wlj/base/adapter/CommonAdapter.java b/base/src/main/java/com/wlj/base/adapter/CommonAdapter.java
new file mode 100755
index 0000000..551b813
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/adapter/CommonAdapter.java
@@ -0,0 +1,86 @@
+package com.wlj.base.adapter;
+
+import java.util.List;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+
+/**
+ * date 2015-5-5
+ * @author Administrator
+ * @param
+ * 通用adapter,不需要更改
+ */
+public abstract class CommonAdapter extends BaseAdapter {
+ protected LayoutInflater mInflater;
+ protected Context mContext;
+ public List mDatas;
+ protected final int mItemLayoutId;
+
+ public CommonAdapter(Context context, List mDatas, int itemLayoutId) {
+ this.mContext = context;
+ this.mInflater = LayoutInflater.from(mContext);
+ this.mDatas = mDatas;
+ this.mItemLayoutId = itemLayoutId;
+ }
+
+ @Override
+ public int getCount() {
+ return mDatas.size();
+ }
+
+ @Override
+ public T getItem(int position) {
+ return mDatas.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final ViewHolder viewHolder = getViewHolder(position, convertView,
+ parent);
+ View view = getListItemview(viewHolder,viewHolder.getConvertView(), getItem(position),
+ position, parent);
+ if (view == null) {
+ return viewHolder.getConvertView();
+ } else {
+ return view;
+ }
+ }
+
+ public ViewHolder getViewHolder(int position, View convertView,
+ ViewGroup parent) {
+ return ViewHolder.get(mContext, convertView, parent, mItemLayoutId,
+ position);
+ }
+
+ public void addDatas(List list) {// 数据追加
+ if (mDatas != null)
+ mDatas.addAll(list);
+ this.notifyDataSetChanged();
+ }
+ public void add(int position,T t){
+ mDatas.add(position, t);
+ }
+ /**
+ *
+ * 返回列表项,作事件处理
+ * @param view itemView
+ * @param item itemdate
+ * @param position
+ * @return 返回的view不为null时为adapter填充数据
+ *
+ *
+ */
+ public abstract View getListItemview(ViewHolder viewHolder, View view,
+ T item, int position, ViewGroup parent);
+}
+
diff --git a/base/src/main/java/com/wlj/base/adapter/ImagePagerAdapter.java b/base/src/main/java/com/wlj/base/adapter/ImagePagerAdapter.java
new file mode 100755
index 0000000..80ffda0
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/adapter/ImagePagerAdapter.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2014 trinea.cn All right reserved. This software is the confidential and proprietary information of
+ * trinea.cn ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only in
+ * accordance with the terms of the license agreement you entered into with trinea.cn.
+ */
+package com.wlj.base.adapter;
+
+import java.util.List;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.wlj.base.RecyclingPagerAdapter;
+import com.wlj.base.util.ListUtils;
+
+/**
+ * ImagePagerAdapter
+ *
+ * @author Trinea 2014-2-23
+ */
+public abstract class ImagePagerAdapter extends RecyclingPagerAdapter {
+
+// private Context context;
+ private List imageIdList;
+
+ private int size;
+ private boolean isInfiniteLoop;
+
+ public ImagePagerAdapter(List imageIdList) {
+// this.context = context;
+ this.imageIdList = imageIdList;
+ this.size = ListUtils.getSize(imageIdList);
+ isInfiniteLoop = false;
+ }
+
+ @Override
+ public int getCount() {
+ // Infinite loop
+ return isInfiniteLoop ? Integer.MAX_VALUE : ListUtils.getSize(imageIdList);
+// return ListUtils.getSize(imageIdList);
+ }
+
+ /**
+ * get really position
+ *
+ * @param position
+ * @return
+ */
+ private int getPosition(int position) {
+ return isInfiniteLoop ? position % size : position;
+ }
+
+ @Override
+ public View getView(int position, View view, ViewGroup container) {
+// ViewHolder holder;
+// if (view == null) {
+// holder = new ViewHolder();
+// view = holder.imageView = new ImageView(context);
+// view.setTag(holder);
+// } else {
+// holder = (ViewHolder)view.getTag();
+// }
+// holder.imageView.setImageResource(imageIdList.get(getPosition(position)));
+
+ return getPageItemview(imageIdList.get(getPosition(position)),view,container);
+ }
+
+ public abstract View getPageItemview(T item, View view, ViewGroup container);
+
+// private static class ViewHolder {
+//
+// ImageView imageView;
+// }
+
+ /**
+ * @return the isInfiniteLoop
+ */
+ public boolean isInfiniteLoop() {
+ return isInfiniteLoop;
+ }
+
+ /**
+ * @param isInfiniteLoop the isInfiniteLoop to set
+ */
+ public ImagePagerAdapter setInfiniteLoop(boolean isInfiniteLoop) {
+ this.isInfiniteLoop = isInfiniteLoop;
+ return this;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/adapter/ListItem.java b/base/src/main/java/com/wlj/base/adapter/ListItem.java
new file mode 100755
index 0000000..521db06
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/adapter/ListItem.java
@@ -0,0 +1 @@
+package com.wlj.base.adapter;
diff --git a/base/src/main/java/com/wlj/base/adapter/MyFragmentStatePagerAdapter.java b/base/src/main/java/com/wlj/base/adapter/MyFragmentStatePagerAdapter.java
new file mode 100755
index 0000000..4202973
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/adapter/MyFragmentStatePagerAdapter.java
@@ -0,0 +1,77 @@
+package com.wlj.base.adapter;
+
+import java.util.List;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.view.PagerAdapter;
+import android.view.ViewGroup;
+
+/**
+ * 页面不缓存
+ * 会保存当前界面,以及下一个界面和上一个界面(如果有),最多保存3个,其他会被销毁掉。
+ * @author wlj
+ *
+ */
+public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
+
+ private List list;
+ public MyFragmentStatePagerAdapter(FragmentManager fm,List _list) {
+ super(fm);
+ list = _list;
+ }
+ /*
+ * (non-Javadoc)
+ * @see android.support.v4.app.FragmentStatePagerAdapter#getItem(int)
+ *
+ * 一个该类中新增的虚函数。
+ * 函数的目的为生成新的 Fragment 对象。
+ * Fragment.setArguments() 这种只会在新建 Fragment 时执行一次的参数传递代码,可以放在这里。
+ * 由于 FragmentStatePagerAdapter.instantiateItem() 在大多数情况下,都将调用 getItem() 来生成新的对象,
+ * 因此如果在该函数中放置与数据集相关的 setter 代码,基本上都可以在 instantiateItem() 被调用时执行,但这和
+ * 设计意图不符。毕竟还有部分可能是不会调用 getItem() 的。因此这部分代码应该放到 instantiateItem() 中
+ */
+ @Override
+ public Fragment getItem(int arg0) {
+ return list.get(arg0);
+ }
+
+ @Override
+ public int getCount() {
+ return list.size();
+ }
+ /*
+ * (non-Javadoc)
+ * @see android.support.v4.app.FragmentStatePagerAdapter#instantiateItem(android.view.ViewGroup, int)
+ *
+ *1.除非碰到 FragmentManager 刚好从 SavedState 中恢复了对应的 Fragment 的情况外,该函数将会调用 getItem() 函数,生成新的 Fragment 对象。新的对象将被 FragmentTransaction.add()。
+ *2.FragmentStatePagerAdapter 就是通过这种方式,每次都创建一个新的 Fragment,而在不用后就立刻释放其资源,来达到节省内存占用的目的的。
+ */
+ @Override
+ public Object instantiateItem(ViewGroup arg0, int arg1) {
+ // TODO Auto-gene rated method stub
+ return super.instantiateItem(arg0, arg1);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.support.v4.app.FragmentStatePagerAdapter#destroyItem(android.view.ViewGroup, int, java.lang.Object)
+ *
+ * 将 Fragment 移除,即调用 FragmentTransaction.remove(),并释放其资源
+ */
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ // TODO Auto-generated method stub
+ super.destroyItem(container, position, object);
+ }
+
+ @Override
+ public int getItemPosition(Object object) {
+// super.getItemPosition(object); 默认为 POSITION_UNCHANGED
+// PagerAdapter.POSITION_UNCHANGED 什么都不做
+// PagerAdapter.POSITION_NONE 则调用 PagerAdapter.destroyItem() 来去掉该对象,
+// 并设置为需要刷新 (needPopulate = true) 以便触发PagerAdapter.instantiateItem() 来生成新的对象
+ return PagerAdapter.POSITION_NONE;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/adapter/ViewHolder.java b/base/src/main/java/com/wlj/base/adapter/ViewHolder.java
new file mode 100755
index 0000000..4831682
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/adapter/ViewHolder.java
@@ -0,0 +1,160 @@
+package com.wlj.base.adapter;
+
+import com.wlj.base.R;
+import com.wlj.base.util.img.ImageLrucache;
+import com.wlj.base.util.img.LoadImage;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.TextView;
+
+public class ViewHolder {
+ private final SparseArray mViews;
+ private int mPosition;
+ private View mConvertView;
+
+ private ViewHolder(Context context, ViewGroup parent, int layoutId,
+ int position) {
+ this.mPosition = position;
+ this.mViews = new SparseArray();
+ mConvertView = LayoutInflater.from(context).inflate(layoutId, parent,
+ false);
+ // setTag
+ mConvertView.setTag(this);
+ }
+ /**
+ * 在position位置添加一个view
+ * @param position
+ */
+ public void addView(int position,View view){
+ mViews.append(position, view);
+ }
+
+ /**
+ * 拿到一个ViewHolder对象
+ *
+ * @param context
+ * @param convertView
+ * @param parent
+ * @param layoutId
+ * @param position
+ * @return
+ */
+ public static ViewHolder get(Context context, View convertView,
+ ViewGroup parent, int layoutId, int position) {
+// MLog.i("ViewHolder:position:"+position);
+// MLog.i("ViewHolder:layoutId:"+layoutId);
+// MLog.i("ViewHolder:(parent==null):"+(parent==null));
+// MLog.i("ViewHolder:(convertView==null):"+(convertView==null));
+ if (convertView == null) {
+ return new ViewHolder(context, parent, layoutId, position);
+ }
+// MLog.i("ViewHolder:(convertView.getTag()==null)"+(convertView.getTag()==null));
+ return (null==(ViewHolder) convertView.getTag())?new ViewHolder(context, parent, layoutId, position):(ViewHolder) convertView.getTag();
+ }
+
+ public View getConvertView() {
+ return mConvertView;
+ }
+
+ /**
+ * 通过控件的Id获取对于的控件,如果没有则加入views
+ *
+ * @param viewId
+ * @return
+ */
+ public T getView(int viewId) {
+ try {
+
+ View view = mViews.get(viewId);
+ if (view == null) {
+ view = mConvertView.findViewById(viewId);
+ mViews.put(viewId, view);
+ }
+ return (T) view;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * 为TextView设置字符串
+ *
+ * @param viewId
+ * @param text
+ * @return
+ */
+ public ViewHolder setText(int viewId, CharSequence text) {
+ TextView view = getView(viewId);
+ view.setText(text);
+ return this;
+ }
+
+ /**
+ * @param viewId
+ * @param ScaleType
+ * @return
+ */
+ public ViewHolder setScaleType(int viewId, ScaleType ScaleType) {
+ ImageView view = getView(viewId);
+ view.setScaleType(ScaleType);
+ return this;
+ }
+
+ /**
+ * 为ImageView设置图片
+ *
+ * @param viewId
+ * @param drawableId
+ * @return
+ */
+ public ViewHolder setImageResource(int viewId, int drawableId) {
+ ImageView view = getView(viewId);
+ view.setImageResource(drawableId);
+ return this;
+ }
+
+ /**
+ * 为ImageView设置图片
+ *
+ * @param viewId
+ * @param bm
+ * @return
+ */
+ public ViewHolder setImageBitmap(int viewId, Bitmap bm) {
+ ImageView view = getView(viewId);
+ view.setImageBitmap(bm);
+ return this;
+ }
+ /**
+ * 为ImageView设置图片
+ *
+ * @param viewId
+ * @param url
+ * @param defaultResId
+ * @return
+ */
+ public ViewHolder setImageByUrl(int viewId, String url,int defaultResId) {
+
+ ImageView view = getView(viewId);
+ if(defaultResId == 0){
+ defaultResId = R.drawable.project_bg;
+ }
+ Bitmap bitmap = ImageLrucache.getInstance().getResourceBitmap(defaultResId, view.getContext());
+ view.setImageBitmap(bitmap);
+ LoadImage.getinstall().addTask(url, view);
+ LoadImage.getinstall().doTask();
+
+ return this;
+ }
+
+ public int getPosition() {
+ return mPosition;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/bean/Banner.java b/base/src/main/java/com/wlj/base/bean/Banner.java
new file mode 100644
index 0000000..7e7fd71
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/bean/Banner.java
@@ -0,0 +1,51 @@
+package com.wlj.base.bean;
+
+import android.app.Activity;
+
+import com.wlj.base.web.BaseURL;
+import com.wlj.base.web.asyn.AsyncRequestModle;
+import com.wlj.base.web.asyn.BaseAsyncModle;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+
+/**
+ *
+ */
+public class Banner extends BaseAsyncModle {
+
+ // SwitchViewPager 获取图片路径
+ private String picPath;
+
+ public Banner() {
+ }
+
+ public Banner(Activity paramActivity) {
+ super(paramActivity);
+ }
+
+ public Banner(JSONObject jo) {
+ super(jo);
+ setPicPath(BaseURL.HOST+jo.optString("pic"));
+ }
+
+ public String getPicPath() {
+ return picPath;
+ }
+
+ public void setPicPath(String picPath) {
+ this.picPath = picPath;
+ }
+
+ @Override
+ public Base parse(JSONObject jsonObject) throws JSONException {
+ return new Banner(jsonObject);
+ }
+
+ @Override
+ public void addRequestParemeter(AsyncRequestModle asRequestModle) throws IOException {
+
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/bean/Base.java b/base/src/main/java/com/wlj/base/bean/Base.java
new file mode 100755
index 0000000..27181d7
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/bean/Base.java
@@ -0,0 +1,101 @@
+package com.wlj.base.bean;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.os.Handler;
+
+import com.wlj.base.util.AppContext;
+import com.wlj.base.util.StringUtils;
+
+/**
+ * 实体基类:实现序列化
+ *
+ * @author wlj
+ * @version 1.0
+ * @created 2012-3-21
+ */
+public abstract class Base implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6547736466184868569L;
+
+ public final static String UTF8 = "UTF-8";
+ private String id;
+ private String key;
+ private String resultStr;
+
+ public Base(){}
+ public Base(JSONObject paramJSONObject) {
+ resultStr = paramJSONObject.toString();
+ }
+
+
+ public abstract Base parse(JSONObject jsonObject) throws JSONException;
+
+ public List parseList(JSONArray data) throws JSONException {
+
+ List list = new ArrayList ();
+
+ for (int i = 0; i < data.length(); i++) {
+ JSONObject tmp = data.optJSONObject(i);
+ list.add(parse(tmp));
+ }
+ return list;
+ };
+ public void getThisfromid(final AppContext mContext, final Handler handle){ };
+ /**
+ * jsonObject 的数据没在 data里面,就按照他自己的格式单独去解析,默认直接掉用parse解析
+ * 这个方法是对特殊jsonObject解析用
+ * @param jsonObject
+ * @return
+ * @throws JSONException
+ */
+ public Base parseBean(JSONObject jsonObject)throws JSONException{
+
+ return parse(jsonObject);
+ };
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getResultStr() {
+ return resultStr;
+ }
+
+ public JSONObject getResultJsonObject() {
+ if(!StringUtils.isEmpty(resultStr)){
+
+ JSONObject jsonObject = null;
+ try {
+ jsonObject = new JSONObject(resultStr);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return jsonObject;
+ }
+ return null;
+ }
+
+
+}
diff --git a/base/src/main/java/com/wlj/base/bean/BaseList.java b/base/src/main/java/com/wlj/base/bean/BaseList.java
new file mode 100755
index 0000000..ad0a534
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/bean/BaseList.java
@@ -0,0 +1,130 @@
+package com.wlj.base.bean;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class BaseList implements Serializable {
+ private static final long serialVersionUID = 1525386978044495919L;
+ private int allCount;
+ private Base baseData;
+ private String id;
+ private int lastpage;
+ private List list;
+ private int pageIndex;
+ private String pic;
+
+ public BaseList() {
+ }
+
+
+ public int getAllCount() {
+
+ return this.allCount;
+ }
+
+ public Base getBaseData() {
+
+ return this.baseData;
+ }
+
+ public String getId() {
+
+ return this.id;
+ }
+
+ public int getLastpage() {
+
+ return this.lastpage;
+ }
+
+ public List getList() {
+
+ return this.list;
+ }
+
+ public int getPageIndex() {
+
+ return this.pageIndex;
+ }
+
+ public String getPic() {
+
+ return this.pic;
+ }
+
+ public BaseList parse(JSONObject paramJSONObject, Base paramBase)
+ throws JSONException {
+
+ setAllCount(paramJSONObject.optInt("count"));
+ int i = paramJSONObject.optInt("pageSize");
+ if (i != 0) {
+ int b = allCount % i;
+ if (b == 0) {
+ setLastpage(allCount / i);
+ } else {
+ setLastpage(getAllCount() / i + 1);
+ }
+ }
+ setPageIndex(paramJSONObject.optInt("page"));
+ JSONObject localJSONObject = paramJSONObject.optJSONObject("data");
+ JSONArray localJSONArray = paramJSONObject.optJSONArray("data");
+ if (localJSONObject != null) {
+ setBaseData(paramBase.parse(localJSONObject));
+ }
+ if (localJSONArray != null) {
+ setList(paramBase.parseList(localJSONArray));
+ }
+ if ((localJSONObject == null) && (localJSONArray == null)) {
+ setBaseData(paramBase.parseBean(paramJSONObject));
+ }
+ return this;
+
+ }
+
+ public BaseList parse(JSONObject paramJSONObject, Class> paramClass)
+ throws Exception {
+ if ((paramClass.newInstance() instanceof Base)) {
+ return parse(paramJSONObject, (Base) paramClass.newInstance());
+ }
+ throw new Exception("传入模型不匹配");
+ }
+
+ public void setAllCount(int paramInt) {
+
+ this.allCount = paramInt;
+ }
+
+ public void setBaseData(Base paramBase) {
+
+ this.baseData = paramBase;
+ }
+
+ public void setId(String paramString) {
+
+ this.id = paramString;
+ }
+
+ public void setLastpage(int paramInt) {
+
+ this.lastpage = paramInt;
+ }
+
+ public void setList(List paramList) {
+
+ this.list = paramList;
+ }
+
+ public void setPageIndex(int paramInt) {
+
+ this.pageIndex = paramInt;
+ }
+
+ public void setPic(String paramString) {
+
+ this.pic = paramString;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/bean/Result.java b/base/src/main/java/com/wlj/base/bean/Result.java
new file mode 100755
index 0000000..2283098
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/bean/Result.java
@@ -0,0 +1,124 @@
+package com.wlj.base.bean;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.util.Xml;
+
+import com.wlj.base.util.AppException;
+import com.wlj.base.util.StringUtils;
+
+/**
+ * 数据操作结果实体类
+ *
+ * @author wlj
+ * @version 1.0
+ * @created 2015-4-10
+ */
+public class Result extends Base {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2563120909303123638L;
+ private int errorCode;
+ private String errorMessage;
+
+ public boolean OK() {
+ return errorCode == 1;
+ }
+
+ /**
+ * 解析调用结果
+ *
+ * @param stream
+ * @return
+ * @throws IOException
+ * @throws XmlPullParserException
+ */
+ public static Result parse(String str) throws AppException {
+ Result res = null;
+ InputStream stream = new ByteArrayInputStream(str.getBytes());
+ // 获得XmlPullParser解析器
+ XmlPullParser xmlParser = Xml.newPullParser();
+ try {
+ xmlParser.setInput(stream , Base.UTF8);
+ // 获得解析到的事件类别,这里有开始文档,结束文档,开始标签,结束标签,文本等等事件。
+ int evtType = xmlParser.getEventType();
+ // 一直循环,直到文档结束
+ while (evtType != XmlPullParser.END_DOCUMENT) {
+ String tag = xmlParser.getName();
+ switch (evtType) {
+
+ case XmlPullParser.START_TAG:
+ // 如果是标签开始,则说明需要实例化对象了
+ if (tag.equalsIgnoreCase("result")) {
+ res = new Result();
+ } else if (res != null) {
+ if (tag.equalsIgnoreCase("errorCode")) {
+ res.errorCode = StringUtils.toInt(
+ xmlParser.nextText(), -1);
+ } else if (tag.equalsIgnoreCase("errorMessage")) {
+ res.errorMessage = xmlParser.nextText().trim();
+ }
+ }
+ break;
+ case XmlPullParser.END_TAG:
+ // 如果遇到标签结束,则把对象添加进集合中
+ break;
+ }
+ // 如果xml没有结束,则导航到下一个节点
+ evtType = xmlParser.next();
+ }
+
+ } catch (XmlPullParserException e) {
+ throw AppException.xml(e);
+ } catch (IOException e) {
+ throw AppException.io(e);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ throw AppException.io(e);
+ }
+ }
+ return res;
+ }
+
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorCode(int errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("RESULT: CODE:%d,MSG:%s", errorCode, errorMessage);
+ }
+
+ @Override
+ public Base parse(JSONObject jsonObject) throws JSONException {
+ Result result = new Result();
+ result.setKey(jsonObject.optString("key"));
+ result.setErrorCode(jsonObject.optInt("statusCode"));
+ result.setErrorMessage(jsonObject.optString("message"));
+ return result;
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/bean/TabBar.java b/base/src/main/java/com/wlj/base/bean/TabBar.java
new file mode 100644
index 0000000..55471cf
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/bean/TabBar.java
@@ -0,0 +1,32 @@
+package com.wlj.base.bean;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class TabBar extends Base {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5261256844506989956L;
+ private String title;
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ @Override
+ public Base parse(JSONObject jsonObject) throws JSONException {
+ return null;
+ }
+
+ @Override
+ public Base parseBean(JSONObject jsonObject) throws JSONException {
+ return super.parseBean(jsonObject);
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/ob/Observer.java b/base/src/main/java/com/wlj/base/ob/Observer.java
new file mode 100755
index 0000000..7063dd4
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/ob/Observer.java
@@ -0,0 +1,11 @@
+package com.wlj.base.ob;
+/**
+ * 观察者必须实现的观察者接口,这个接口只有update()一个方法,当主题状态改变时它被调用
+ * @author wlj
+ *
+ */
+public interface Observer {
+
+
+ void update(Subject subject, Object o);
+}
diff --git a/base/src/main/java/com/wlj/base/ob/ObserversImageView.java b/base/src/main/java/com/wlj/base/ob/ObserversImageView.java
new file mode 100755
index 0000000..9cf6036
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/ob/ObserversImageView.java
@@ -0,0 +1,85 @@
+package com.wlj.base.ob;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import com.wlj.base.R;
+import com.wlj.base.util.Log;
+import com.wlj.base.util.img.ImageLrucache;
+import com.wlj.base.util.img.LoadImage;
+
+public class ObserversImageView extends ImageView implements Observer {
+
+ public ObserversImageView(Context context) {
+ super(context);
+ }
+
+ public ObserversImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ /**
+ * 上一次可见状态
+ */
+ boolean lastVisible ;
+ @Override
+ public void update(Subject subject, Object o) {
+
+ ObserversScrollView os = (ObserversScrollView)subject;
+ if(os.isChildVisible(this) ){
+ if( !lastVisible){
+ lastVisible = true;
+ if(getTag() == null){
+ //==nul的原来就是lproject_bg 不用在此加载
+// setImageBitmap(BitmapCache.getInstance().getBitmap( R.drawable.project_bg, getContext()));
+ Log.w("dd","加载project_bg"+ getTag());
+ }else{
+ LoadImage.getinstall().addTask(getTag()+"", this);
+ LoadImage.getinstall().doTask();
+ Log.w("dd","加载view ");
+ }
+ }
+ } else {
+ if(lastVisible){
+ lastVisible = false;
+ setImageBitmap(ImageLrucache.getInstance().getResourceBitmap( R.drawable.project_bg, getContext()));
+ Log.w("dd","view 拜拜 " +getTag() );
+ }
+ }
+
+// //获取在整个屏幕内的绝对坐标,注意这个值是要从屏幕顶端算起,也就是包括了通知栏的高度。
+// int[] location = new int[2];
+// getLocationOnScreen(location);
+// Rect r = new Rect();
+// Rect g = new Rect();
+// getLocalVisibleRect(r);//获取视图本身可见的坐标区域,坐标以自己的左上角为原点
+// getGlobalVisibleRect(g);//方法的作用是获取视图在屏幕坐标中的可视区域
+// if (o instanceof Integer) {
+// int statusbarheight = StatusBarHeight.getStatusBarHeight3(getContext());//通知栏高
+// int curViewTopForScreenTop = location[1] ;//当前view距屏幕顶部高
+// int curViewTop = getMeasuredHeight();// view的高度
+// int scrollY = (Integer) o;//pix scroll滚动到的位置
+//
+// DisplayMetrics metric = new DisplayMetrics();
+// Activity a = (Activity)getContext();
+// a.getWindowManager().getDefaultDisplay().getMetrics(metric);
+//
+// int hh = curViewTopForScreenTop- statusbarheight;
+// Log.d("dd",scrollY+" hh ="+hh);
+// if(hh+curViewTop > 0&& hh < metric.heightPixels){
+// Log.w("dd","view 可见");
+// }else{
+// Log.w("dd","view bujianle ");
+// }
+//
+// }
+
+ }
+
+ @Override
+ public void setImageBitmap(Bitmap bm) {
+
+ super.setImageBitmap(bm);
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/ob/ObserversScrollView.java b/base/src/main/java/com/wlj/base/ob/ObserversScrollView.java
new file mode 100755
index 0000000..d0d94d6
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/ob/ObserversScrollView.java
@@ -0,0 +1,142 @@
+package com.wlj.base.ob;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+public class ObserversScrollView extends ScrollView implements Subject {
+
+ public ObserversScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ observers = new ArrayList();
+ }
+
+ private ArrayList observers;
+
+ @Override
+ public void registerObserver(Observer arg0) {
+ if (arg0 == null) {
+ throw new NullPointerException("observer == null");
+ }
+ synchronized (this) {
+ if (!observers.contains(arg0))
+ observers.add(arg0);
+ }
+ }
+
+ @Override
+ public synchronized void removeObserver(Observer arg0) {
+ if (observers.contains(arg0)) {
+ observers.remove(arg0);
+ }
+ }
+
+ @Override
+ public void notifyObservers(Object o) {
+ int size = 0;
+ Observer[] arrays = null;
+ synchronized (this) {
+ size = observers.size();
+ arrays = new Observer[size];
+ observers.toArray(arrays);
+ }
+ if (arrays != null) {
+ for (Observer observer : arrays) {
+ observer.update(this, o);
+ }
+ }
+ }
+ @Override
+ public synchronized void deleteObservers() {
+ observers.clear();
+ }
+
+ /**
+ * 界面加载完后,调用的方法
+ */
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ init(this);
+ }
+ /**
+ * 界面加载完毕
+ * @param sv01
+ */
+ private void init(ViewGroup sv01 ){
+ int childCount = sv01.getChildCount();
+
+ for (int i = 0; i < childCount; i++) {
+ View view = sv01.getChildAt(i);
+
+ if(view instanceof ObserversImageView ){
+ registerObserver((ObserversImageView)view);
+ }
+ if(view instanceof ViewGroup){
+ init((ViewGroup)view );
+ }
+
+ }
+ touch();
+ }
+
+ @Override
+ public void computeScroll() {
+ super.computeScroll();
+ }
+
+ public boolean isChildVisible(View child){
+ if(child==null){
+ return false;
+ }
+ Rect scrollBounds = new Rect();
+ getHitRect(scrollBounds);//getHitRect 获取控件所在的矩阵范围函数
+ return child.getLocalVisibleRect(scrollBounds);
+ }
+ int currentScroll;
+
+ /**
+ * 设置本身的touch事件
+ */
+ private void touch() {
+ setOnTouchListener(new OnTouchListener() {
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ currentScroll = getScrollY();
+ postDelayed(scrollCheckTask, 300);
+ }
+ return false;
+ }
+ });
+ }
+
+ Runnable scrollCheckTask = new Runnable() {
+ @Override
+ public void run() {
+ int newScroll = getScrollY();
+ if (currentScroll == newScroll) {
+ notifyObservers(null);
+ // if(onWaterfallScrollListener !=null){
+ // if(isAtTop()){
+ // //TODO: onScrollStoppedAtTop;
+ // }
+ // if(isScrollViewAtBottom(sv)){
+ // //TODO: onScrollStoppedAtBottom;
+ // }
+ // }
+ } else {
+ currentScroll = getScrollY();
+ postDelayed(scrollCheckTask, 300);
+ // }
+ }
+ }
+ };
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/ob/Subject.java b/base/src/main/java/com/wlj/base/ob/Subject.java
new file mode 100755
index 0000000..4bfe16b
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/ob/Subject.java
@@ -0,0 +1,18 @@
+package com.wlj.base.ob;
+
+/**
+ * 主题接口,对象使用此接口注册为观察着,或者把自己重观察者中删除
+ * @author wlj
+ *
+ */
+public interface Subject {
+
+ public void registerObserver(Observer arg0);
+ public void removeObserver(Observer arg0);
+ public void notifyObservers(Object o);
+ /**
+ *
+ */
+ public void deleteObservers();
+
+}
diff --git a/base/src/main/java/com/wlj/base/ui/BaseFragment.java b/base/src/main/java/com/wlj/base/ui/BaseFragment.java
new file mode 100755
index 0000000..63deb38
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/ui/BaseFragment.java
@@ -0,0 +1,82 @@
+package com.wlj.base.ui;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import com.wlj.base.util.Log;
+
+/**
+ * 应用程序Fragment的基类
+ *
+ * @author
+ * @version 1.0
+ * @created 2012-9-18
+ */
+public abstract class BaseFragment extends Fragment {
+ protected Context mcontext;
+ protected View view;// infalte的布局
+ public BaseFragment(){ }
+ /*
+ * 创建的时才加载
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ /**
+ * SOFT_INPUT_ADJUST_NOTHING: 不调整(输入法完全直接覆盖住,未开放此参数)
+ SOFT_INPUT_ADJUST_PAN: 把整个Layout顶上去露出获得焦点的EditText,不压缩多余空间,见图1
+ SOFT_INPUT_ADJUST_RESIZE: 整个Layout重新编排,重新分配多余空间,见图2
+ SOFT_INPUT_ADJUST_UNSPECIFIED: 系统自己根据内容自行选择上两种方式的一种执行(默认配置)
+ */
+// getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+// getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+// getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
+
+ mcontext = getActivity().getApplicationContext();
+ Log.w("dd", "onCreate");
+ }
+
+ /**
+ * 每次加载 都会调用onCreateView
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ Log.w("dd", "onCreateView");
+ if (null == view) {
+ view = inflater.inflate(getlayout(), null);
+ view.setMinimumHeight(((WindowManager) getActivity()
+ .getSystemService(Context.WINDOW_SERVICE))
+ .getDefaultDisplay().getHeight());
+ view.setMinimumWidth(((WindowManager) getActivity()
+ .getSystemService(Context.WINDOW_SERVICE))
+ .getDefaultDisplay().getWidth());
+ initView();
+ } else {
+ FrameLayout viewParent = (FrameLayout) view.getParent();
+ if(viewParent != null){
+ viewParent.removeAllViews();
+ viewParent = new FrameLayout(mcontext);
+ viewParent.addView(view);
+ return viewParent;
+ }
+ }
+
+ return view;
+ }
+
+ /**
+ * Fragment的布局
+ *
+ * @return
+ */
+ protected abstract int getlayout();
+
+ protected abstract void initView();
+}
diff --git a/base/src/main/java/com/wlj/base/ui/BaseFragmentActivity.java b/base/src/main/java/com/wlj/base/ui/BaseFragmentActivity.java
new file mode 100755
index 0000000..f80defc
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/ui/BaseFragmentActivity.java
@@ -0,0 +1,70 @@
+package com.wlj.base.ui;
+
+import com.wlj.base.R;
+import com.wlj.base.util.AppManager;
+import com.wlj.base.util.statusbar.StatusBarUtil;
+
+import android.annotation.SuppressLint;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.LayoutRes;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AppCompatActivity;
+import android.view.Window;
+import android.view.WindowManager;
+
+/**
+ * 应用程序Activity的基类
+ *
+ * @author
+ * @version 1.0
+ * @created 2012-9-18
+ */
+
+public class BaseFragmentActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+
+ AppManager.getAppManager().addActivity(this);
+
+ }
+
+ @Override
+ public void setContentView(@LayoutRes int layoutResID) {
+ super.setContentView(layoutResID);
+ setStatusBar();
+ }
+
+ protected void setStatusBar() {
+
+ StatusBarUtil.setTranslucent(this, 127);
+
+ };
+
+ @Override
+ protected void onPause() {
+ System.gc();
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ // 结束Activity&从堆栈中移除
+ AppManager.getAppManager().finishActivity(this);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+
+ // 其实这里什么都不要做
+ super.onConfigurationChanged(newConfig);
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/update/DownLoadManager.java b/base/src/main/java/com/wlj/base/update/DownLoadManager.java
new file mode 100755
index 0000000..2cd26a1
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/update/DownLoadManager.java
@@ -0,0 +1,67 @@
+package com.wlj.base.update;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.wlj.base.util.AppConfig;
+import com.wlj.base.util.RequestException;
+
+import android.app.ProgressDialog;
+import android.os.Environment;
+
+public class DownLoadManager {
+
+ private static boolean cancelUpdate = false;
+
+ public static boolean isCancelUpdate() {
+ return cancelUpdate;
+ }
+
+ public static void setCancelUpdate(boolean cancelUpdate) {
+ DownLoadManager.cancelUpdate = cancelUpdate;
+ }
+
+ public static File getFileFromServer(String path, ProgressDialog pd) throws IOException, RequestException
+ {
+ if (Environment.getExternalStorageState().equals(
+ Environment.MEDIA_MOUNTED)) {
+ URL url = new URL(path);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setConnectTimeout(5000);
+ //
+ pd.setMax(conn.getContentLength());
+ InputStream is = conn.getInputStream();
+// http://121.40.177.251:6940/LSYiGou.apk
+
+ File file = new File(AppConfig.getAppConfig().getImagePath(),path.substring(path.lastIndexOf("/"),path.length()));
+ FileOutputStream fos = new FileOutputStream(file);
+ BufferedInputStream bis = new BufferedInputStream(is);
+ byte[] buffer = new byte[1024];
+ int len;
+ int total = 0;
+ while ((len = bis.read(buffer)) != -1) {
+ fos.write(buffer, 0, len);
+ total += len;
+ //
+ pd.setProgress(total);
+ if (isCancelUpdate()) {
+ fos.close();
+ bis.close();
+ is.close();
+ throw new RequestException("取消下载成功");
+ }
+ }
+ fos.close();
+ bis.close();
+ is.close();
+ return file;
+ }
+ throw new RequestException("没找到sd卡");
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/update/Update.java b/base/src/main/java/com/wlj/base/update/Update.java
new file mode 100755
index 0000000..ee4ee56
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/update/Update.java
@@ -0,0 +1,293 @@
+package com.wlj.base.update;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.view.WindowManager;
+import android.widget.Toast;
+
+import com.wlj.base.util.ExecutorServices;
+import com.wlj.base.util.RequestException;
+
+public class Update {
+ private UpdateInfo info = new UpdateInfo();
+
+ private Context mContext;
+ private String path;
+ private NextStep nextStep;
+
+ public static final int no_update = 5;
+ public static final int version_exception = 1;
+ public static final int service_timeout = -1;
+ public static final int download_failed = -2;
+
+ private boolean comeFromService;
+
+
+ public void setComeFromService(boolean comeFromService) {
+ this.comeFromService = comeFromService;
+ }
+
+ public enum state {
+ no_update ,
+ version_exception,
+ service_timeout,
+ download_failed,
+ have_update
+ }
+ /**
+ *
+ * @param mContext
+ * @param path 服务器地址
+ * @param nextStep 后续操作
+ */
+ public Update(Context mContext,String path,NextStep nextStep){
+ this.mContext = mContext;
+ this.path = path;
+ this.nextStep = nextStep;
+ }
+
+ /**
+ * 获取当前程序的版本号
+ */
+ public String getVersionName() throws Exception {
+ // 获取packagemanager的实例
+ PackageManager packageManager = mContext.getPackageManager();
+ // getPackageName()是你当前类的包名,0代表是获取版本信息
+ PackageInfo packInfo = packageManager.getPackageInfo(mContext.getPackageName(),0);
+ return packInfo.versionName;
+ }
+ /*
+ * 进入程序的主界面
+ */
+ public interface NextStep{
+
+ public void next(state what);
+ }
+ /**
+ *只检查是否有更新 就返回
+ */
+ public void onlyCheck(){
+ onlyCheck = true;
+ ExecutorServices.getExecutorService().execute(new CheckVersionTask());
+ }
+ /**
+ * 检查更新 并弹出处更新提示框
+ */
+ public void check(){
+
+ ExecutorServices.getExecutorService().execute(new CheckVersionTask());
+ }
+ /*
+ * 从服务器获取xml解析并进行比对版本号
+ */
+ private class CheckVersionTask implements Runnable {
+
+ public void run() {
+ try {
+
+ URL url = new URL(path);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setConnectTimeout(5000);
+ InputStream is = conn.getInputStream();
+ info.parse(is);
+
+ UpdateInfo.setServerVersion(info.getVersion());
+ UpdateInfo.setLocalVersion(getVersionName());
+
+ String serviceversion = info.getVersion();
+ if (serviceversion.equals(getVersionName())) {
+ // Log.i(TAG,"版本号相同无需升级");
+ Message msg = new Message();
+ msg.what = no_update;
+ handler.sendMessage(msg);
+ } else {
+ // Log.i(TAG,"版本号不同 ,提示用户升级 ");
+ Message msg = new Message();
+ msg.what = version_exception;
+ handler.sendMessage(msg);
+ }
+ } catch (Exception e) {
+ // 连接服务器超时
+ Message msg = new Message();
+ msg.what = service_timeout;
+ handler.sendMessage(msg);
+ }
+ }
+ }
+ /**
+ * 弹出对话框通知用户更新程序
+ *
+ * 弹出对话框的步骤: 1.创建alertDialog的builder. 2.要给builder设置属性, 对话框的内容,样式,按钮
+ * 3.通过builder 创建一个对话框 4.对话框show()出来
+ */
+ protected void showUpdataDialog() {
+ Builder builer = new Builder(mContext);
+ builer.setTitle("版本升级");
+ builer.setMessage(info.getDescription());
+ builer.setCancelable(false);
+ // 当点确定按钮时从服务器上下载 新的apk 然后安装
+ builer.setPositiveButton("确定", new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // Log.i(TAG,"下载apk,更新");
+ downLoadApk();
+ }
+ });
+ // 当点取消按钮时进行登录
+ builer.setNegativeButton("取消", new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ Message msg = new Message();
+ msg.what = download_failed;
+ msg.obj = null;
+ handler.sendMessage(msg);
+ }
+ });
+ AlertDialog dialog = builer.create();
+ if(comeFromService){
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ }
+ dialog.show();
+ }
+
+ ProgressDialog pd;
+
+ /**
+ * 从服务器中下载APK
+ */
+ protected void downLoadApk() {
+ // 进度条对话框
+ pd = new ProgressDialog(mContext);
+ pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ pd.setCancelable(false);
+ // 更新时候的启动按钮
+ pd.setButton(DialogInterface.BUTTON_POSITIVE,"取消", new OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ DownLoadManager.setCancelUpdate(true);
+ }
+ });
+ pd.setMessage("正在下载...");
+ if(comeFromService){
+ pd.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ }
+ pd.show();
+
+ ExecutorServices.getExecutorService().execute(new Runnable() {
+ @Override
+ public void run() {
+ Message msg = Message.obtain();
+ try {
+ File file = DownLoadManager.getFileFromServer(info.getUrl(), pd);
+ Thread.sleep(3000);
+ if (!DownLoadManager.isCancelUpdate()) {
+ pd.dismiss(); // 结束掉进度条对话框
+ installApk(file);
+ }
+ } catch (Exception e) {
+ msg.what = download_failed;
+ msg.obj = e;
+ }
+ pd.dismiss(); // 结束掉进度条对话框
+ handler.sendMessage(msg);
+ }
+ });
+ }
+
+ // 安装apk
+ protected void installApk(File file) {
+ // System.out.println("开始安装");
+ Intent intent = new Intent();
+ // 执行动作
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ // 执行的数据类型
+ intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
+ mContext.startActivity(intent);
+ }
+
+ private Handler handler = new Handler(Looper.myLooper()) {
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+
+ // 不需要升级直接下一步
+ case no_update:
+ nextStep.next(state.no_update);
+ break;
+
+ // 对话框通知用户升级程序
+ case version_exception:
+ try {
+ UpdateInfo.setServerVersion(info.getVersion());
+ UpdateInfo.setLocalVersion(getVersionName());
+ System.out.println("服务器上的版本号为1:----->" + info.getVersion());
+ System.out.println("本地的版本号为1:----->" + getVersionName());
+
+ if (!info.getVersion().equals("")&& Double.parseDouble(info.getVersion()) > Double.parseDouble(getVersionName())) {
+ if(onlyCheck){
+ nextStep.next(state.have_update);
+ }else{
+ showUpdataDialog();
+ }
+ } else {
+ nextStep.next(state.version_exception);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Toast.makeText(mContext,"版本号异常" + UpdateInfo.getLocalVersion()+ "=ServiceVersion :" + info.getVersion(),
+ Toast.LENGTH_LONG).show();
+ nextStep.next(state.version_exception);
+ }
+
+ break;
+
+ // 服务器超时
+ case service_timeout:
+ Toast.makeText(mContext,"获取服务器更新信息超时",Toast.LENGTH_SHORT).show();
+ nextStep.next(state.service_timeout);
+ break;
+
+ // 下载apk失败
+ case download_failed:
+ Object obj = msg.obj;
+
+ if(obj instanceof RequestException){
+ Exception e = (Exception)obj;
+ Toast.makeText(mContext,e.getMessage()+"",Toast.LENGTH_SHORT).show();
+ }else if(obj instanceof IOException ){
+ Toast.makeText(mContext,"下载失败",Toast.LENGTH_SHORT).show();
+ }
+ nextStep.next(state.download_failed);
+ break;
+ }
+ }
+ };
+
+ private boolean onlyCheck;
+
+ public static Update parse(InputStream http_get) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/update/UpdateInfo.java b/base/src/main/java/com/wlj/base/update/UpdateInfo.java
new file mode 100755
index 0000000..cc6ca5a
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/update/UpdateInfo.java
@@ -0,0 +1,118 @@
+package com.wlj.base.update;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.util.Xml;
+
+import com.wlj.base.bean.Base;
+import com.wlj.base.util.AppException;
+
+public class UpdateInfo extends Base {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1253578920138561513L;
+ private String version;
+ private String url;
+ private String description;
+ private static String content;
+ private static String serverVersion;
+ private static String localVersion;
+
+ public static String getServerVersion() {
+ return serverVersion;
+ }
+
+ public static void setServerVersion(String serverVersion) {
+ UpdateInfo.serverVersion = serverVersion;
+ }
+
+ public static String getLocalVersion() {
+ return localVersion;
+ }
+
+ public static void setLocalVersion(String localVersion) {
+ UpdateInfo.localVersion = localVersion;
+ }
+
+ public static String getContent() {
+ return content;
+ }
+
+ public static void setContent(String content) {
+ UpdateInfo.content = content;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /*
+ * 用pull解析器解析服务器返回的xml文件 (xml封装了版本号)
+ */
+ public UpdateInfo parse(InputStream is) throws AppException {
+
+ XmlPullParser parser = Xml.newPullParser();
+ try {
+ parser.setInput(is, "utf-8");
+ // 设置解析的数据源
+ int type = parser.getEventType();
+
+ while (type != XmlPullParser.END_DOCUMENT) {
+ switch (type) {
+ case XmlPullParser.START_TAG:
+ if ("version".equals(parser.getName())) {
+ setVersion(parser.nextText()); // 获取版本号
+ } else if ("url".equals(parser.getName())) {
+ setUrl(parser.nextText()); // 获取要升级的APK文件
+ } else if ("description".equals(parser.getName())) {
+ setDescription(parser.nextText()); // 获取该文件的信息
+ } else if ("content".equals(parser.getName())) {
+ UpdateInfo.setContent(parser.nextText());
+ }
+ break;
+ }
+ type = parser.next();
+ }
+ } catch (XmlPullParserException e) {
+ throw AppException.xml(e);
+ } catch (IOException e) {
+ throw AppException.io(e);
+ }
+ return this;
+ }
+
+ @Override
+ public Base parse(JSONObject jsonObject) throws JSONException {
+
+ return null;
+ }
+
+
+}
diff --git a/base/src/main/java/com/wlj/base/util/AppConfig.java b/base/src/main/java/com/wlj/base/util/AppConfig.java
new file mode 100755
index 0000000..7c7feae
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/AppConfig.java
@@ -0,0 +1,177 @@
+package com.wlj.base.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Properties;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Environment;
+import android.preference.PreferenceManager;
+
+import com.orhanobut.logger.Logger;
+import com.wlj.base.R;
+import com.wlj.base.util.img.ImageFileCache;
+
+/**
+ * 应用程序配置类:用于保存用户相关信息及设置
+ *
+ * @version 1.0
+ * @created 2012-3-21
+ */
+public class AppConfig {
+
+ private final static String APP_CONFIG = "config";
+
+ public final static String CONF_APP_UNIQUEID = "APP_UNIQUEID";
+ public final static String CONF_COOKIE = "cookie";
+ public final static String CONF_ACCESSTOKEN = "accessToken";
+ public final static String CONF_ACCESSSECRET = "accessSecret";
+ public final static String CONF_EXPIRESIN = "expiresIn";
+ public final static String CONF_LOAD_IMAGE = "perf_loadimage";
+
+ public final static String SAVE_IMAGE_PATH = "save_image_path";
+
+ private static Context mContext;
+ private static AppConfig appConfig;
+
+ public final static String CONF_FIRSTSTART = "perf_firststart";
+ public final static String CONF_TYPT = "type";
+ public final static String CONF_NAME = "name";
+ public final static String CONF_KEY = "key";
+ public final static String CONF_PHONE = "phone";
+
+ public static AppConfig getAppConfig( ) {
+
+ if (appConfig == null) {
+ mContext = AppContext.getAppContext();
+ appConfig = new AppConfig();
+ }
+
+ return appConfig;
+ }
+
+ public String getImagePath(){
+
+ //设置保存图片的路径
+ String saveImagePath = get(AppConfig.SAVE_IMAGE_PATH);
+
+ if(StringUtils.isEmpty(saveImagePath)){
+ saveImagePath = ImageFileCache.getSDPath()+ File.separator + mContext.getString(R.string.app_name)+ File.separator;
+ set(AppConfig.SAVE_IMAGE_PATH, saveImagePath);
+ }
+ return saveImagePath;
+ }
+
+ /**
+ * 获取Preference设置
+ */
+ public static SharedPreferences getSharedPreferences(Context context) {
+ return PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ /**
+ * 是否加载显示文章图片
+ */
+ public static boolean isLoadImage(Context context) {
+ return getSharedPreferences(context).getBoolean(CONF_LOAD_IMAGE, true);
+ }
+
+ public String getCookie() {
+ return get(CONF_COOKIE);
+ }
+
+ public void setAccessToken(String accessToken) {
+ set(CONF_ACCESSTOKEN, accessToken);
+ }
+
+ public String getAccessToken() {
+ return get(CONF_ACCESSTOKEN);
+ }
+
+ public void setAccessSecret(String accessSecret) {
+ set(CONF_ACCESSSECRET, accessSecret);
+ }
+
+ public String getAccessSecret() {
+ return get(CONF_ACCESSSECRET);
+ }
+
+ public void setExpiresIn(long expiresIn) {
+ set(CONF_EXPIRESIN, String.valueOf(expiresIn));
+ }
+
+ public long getExpiresIn() {
+ return StringUtils.toLong(get(CONF_EXPIRESIN));
+ }
+
+ public String get(String key) {
+ Properties props = get();
+ return((props != null)&&(props.getProperty(key)!= null))? props.getProperty(key) : "";
+ }
+
+
+ public Properties get() {
+ FileInputStream fis = null;
+ Properties props = new Properties();
+ try {
+ // 读取files目录下的config
+ // fis = activity.openFileInput(APP_CONFIG);
+
+ // 读取app_config目录下的config
+ File dirConf = mContext.getDir(APP_CONFIG, Context.MODE_PRIVATE);
+ fis = new FileInputStream(dirConf.getPath() + File.separator + APP_CONFIG);
+ props.load(fis);
+ } catch (Exception e) {
+ } finally {
+ try {
+ fis.close();
+ } catch (Exception e) {
+ }
+ }
+ return props;
+ }
+
+ private void setProps(Properties p) {
+ FileOutputStream fos = null;
+ try {
+ // 把config建在files目录下
+ // fos = activity.openFileOutput(APP_CONFIG, Context.MODE_PRIVATE);
+
+ // 把config建在(自定义)app_config的目录下
+ File dirConf = mContext.getDir(APP_CONFIG, Context.MODE_PRIVATE);
+ File conf = new File(dirConf, APP_CONFIG);
+ fos = new FileOutputStream(conf);
+
+ p.store(fos, null);
+ fos.flush();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ fos.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ public void set(Properties ps) {
+ Properties props = get();
+ props.putAll(ps);
+ setProps(props);
+ }
+
+ public void set(String key, String value) {
+ Properties props = get();
+ props.setProperty(key, value);
+ setProps(props);
+ }
+
+ public void remove(String... key) {
+ Properties props = get();
+ for (String k : key)
+ props.remove(k);
+ setProps(props);
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/AppContext.java b/base/src/main/java/com/wlj/base/util/AppContext.java
new file mode 100755
index 0000000..edd3b51
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/AppContext.java
@@ -0,0 +1,634 @@
+package com.wlj.base.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.UUID;
+
+import android.Manifest;
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.media.AudioManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.orhanobut.logger.Logger;
+
+/**
+ * 全局应用程序类:用于保存和调用全局应用配置及访问网络数据
+ * @author wlj
+ * @version 1.0
+ * @created 2012-3-21
+ */
+public class AppContext extends Application {
+
+ public static final int NETTYPE_WIFI = 0x01;
+ public static final int NETTYPE_CMWAP = 0x02;
+ public static final int NETTYPE_CMNET = 0x03;
+
+ public static final int PAGE_SIZE = 20;//默认分页大小
+ private static final int CACHE_TIME = 60*60000;//缓存失效时间
+
+ private Hashtable memCacheRegion = new Hashtable();
+
+ private String saveImagePath;//保存图片路径
+ private static AppContext appContext;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ //注册App异常崩溃处理器
+ Thread.setDefaultUncaughtExceptionHandler(AppException.getAppExceptionHandler());
+ appContext = this;
+ init();
+ }
+
+ /**
+ * 初始化
+ */
+ private void init(){
+
+ }
+ public static AppContext getAppContext() {
+ return appContext;
+ }
+
+ public boolean islogin(){
+
+ String property = getProperty(AppConfig.CONF_KEY);
+
+ if(!"".equals(property)){
+ return true;
+ }
+
+ return false;
+ }
+
+ public void loginOut() {
+ setProperty(AppConfig.CONF_KEY,"");
+ }
+
+
+ /**
+ * 判断是否有网络
+ */
+ public boolean isNetworkAvailable() {
+ if (checkCallingOrSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED ||
+ checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED
+ ) {
+
+ return false;
+ } else {
+ ConnectivityManager connectivity = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
+
+ if (connectivity == null) {
+ Logger.w("Utility", "couldn't get connectivity manager");
+ } else {
+ NetworkInfo[] info = connectivity.getAllNetworkInfo();
+ if (info != null) {
+ for (int i = 0; i < info.length; i++) {
+ if (info[i].isAvailable()) {
+// Logger.d( "network is available");
+ return true;
+ }
+ }
+ }
+ }
+ }
+ Logger.d("Utility", "network is not available");
+ return false;
+ }
+
+// /**
+// * 检测当前系统声音是否为正常模式
+// * @return
+// */
+// public boolean isAudioNormal() {
+// AudioManager mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
+// return mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL;
+// }
+//
+// /**
+// * 应用程序是否发出提示音
+// * @return
+// */
+// public boolean isAppSound() {
+// return isAudioNormal() && isVoice();
+// }
+//
+// /**
+// * 检测网络是否可用
+// * @return
+// */
+// public boolean isNetworkConnected() {
+// ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+// NetworkInfo ni = cm.getActiveNetworkInfo();
+// return ni != null && ni.isConnectedOrConnecting();
+// }
+//
+// /**
+// * 获取当前网络类型
+// * @return 0:没有网络 1:WIFI网络 2:WAP网络 3:NET网络
+// */
+// public int getNetworkType() {
+// int netType = 0;
+// ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+// NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
+// if (networkInfo == null) {
+// return netType;
+// }
+// int nType = networkInfo.getType();
+// if (nType == ConnectivityManager.TYPE_MOBILE) {
+// String extraInfo = networkInfo.getExtraInfo();
+// if(!StringUtils.isEmpty(extraInfo)){
+// if (extraInfo.toLowerCase().equals("cmnet")) {
+// netType = NETTYPE_CMNET;
+// } else {
+// netType = NETTYPE_CMWAP;
+// }
+// }
+// } else if (nType == ConnectivityManager.TYPE_WIFI) {
+// netType = NETTYPE_WIFI;
+// }
+// return netType;
+// }
+ /**
+ * 判断缓存数据是否可读
+ * @param cachefile
+ * @return
+ */
+ public boolean isReadDataCache(String cachefile)
+ {
+ return readObject(cachefile) != null;
+ }
+// /**
+// * 判断当前版本是否兼容目标版本的方法
+// * @param VersionCode
+// * @return
+// */
+// public static boolean isMethodsCompat(int VersionCode) {
+// int currentVersion = Build.VERSION.SDK_INT;
+// return currentVersion >= VersionCode;
+// }
+//
+ /**
+ * 获取App安装包信息
+ * @return
+ */
+ public PackageInfo getPackageInfo() {
+ PackageInfo info = null;
+ try {
+ info = getPackageManager().getPackageInfo(getPackageName(), 0);
+ } catch (NameNotFoundException e) {
+ e.printStackTrace(System.err);
+ }
+ if(info == null) info = new PackageInfo();
+ return info;
+ }
+//
+// /**
+// * 获取App唯一标识
+// * @return
+// */
+// public String getAppId() {
+// String uniqueID = getProperty(AppConfig.CONF_APP_UNIQUEID);
+// if(StringUtils.isEmpty(uniqueID)){
+// uniqueID = UUID.randomUUID().toString();
+// setProperty(AppConfig.CONF_APP_UNIQUEID, uniqueID);
+// }
+// return uniqueID;
+// }
+//
+// /**
+// * 设置是否加载文章图片
+// * @param b
+// */
+// public void setConfigLoadimage(boolean b)
+// {
+// setProperty(AppConfig.CONF_LOAD_IMAGE, String.valueOf(b));
+// }
+//
+// /**
+// * 是否发出提示音
+// * @return
+// */
+// public boolean isVoice()
+// {
+// String perf_voice = getProperty(AppConfig.CONF_VOICE);
+// //默认是开启提示声音
+// if(StringUtils.isEmpty(perf_voice))
+// return true;
+// else
+// return StringUtils.toBool(perf_voice);
+// }
+//
+// /**
+// * 设置是否发出提示音
+// * @param b
+// */
+// public void setConfigVoice(boolean b)
+// {
+// setProperty(AppConfig.CONF_VOICE, String.valueOf(b));
+// }
+//
+// /**
+// * 是否启动检查更新
+// * @return
+// */
+// public boolean isCheckUp()
+// {
+// String perf_checkup = getProperty(AppConfig.CONF_CHECKUP);
+// //默认是开启
+// if(StringUtils.isEmpty(perf_checkup))
+// return true;
+// else
+// return StringUtils.toBool(perf_checkup);
+// }
+//
+// /**
+// * 设置启动检查更新
+// * @param b
+// */
+// public void setConfigCheckUp(boolean b)
+// {
+// setProperty(AppConfig.CONF_CHECKUP, String.valueOf(b));
+// }
+//
+// /**
+// * 是否左右滑动
+// * @return
+// */
+// public boolean isScroll()
+// {
+// String perf_scroll = getProperty(AppConfig.CONF_SCROLL);
+// //默认是关闭左右滑动
+// if(StringUtils.isEmpty(perf_scroll))
+// return false;
+// else
+// return StringUtils.toBool(perf_scroll);
+// }
+//
+// /**
+// * 设置是否左右滑动
+// * @param b
+// */
+// public void setConfigScroll(boolean b)
+// {
+// setProperty(AppConfig.CONF_SCROLL, String.valueOf(b));
+// }
+//
+// /**
+// * 是否Https登录
+// * @return
+// */
+// public boolean isHttpsLogin()
+// {
+// String perf_httpslogin = getProperty(AppConfig.CONF_HTTPS_LOGIN);
+// //默认是http
+// if(StringUtils.isEmpty(perf_httpslogin))
+// return false;
+// else
+// return StringUtils.toBool(perf_httpslogin);
+// }
+//
+// /**
+// * 设置是是否Https登录
+// * @param b
+// */
+// public void setConfigHttpsLogin(boolean b)
+// {
+// setProperty(AppConfig.CONF_HTTPS_LOGIN, String.valueOf(b));
+// }
+//
+// /**
+// * 清除保存的缓存
+// */
+// public void cleanCookie()
+// {
+// removeProperty(AppConfig.CONF_COOKIE);
+// }
+//
+ /**
+ * 判断缓存是否存在
+ * @param cachefile
+ * @return
+ */
+ private boolean isExistDataCache(String cachefile)
+ {
+ boolean exist = false;
+ File data = getFileStreamPath(cachefile);
+ if(data.exists())
+ exist = true;
+ return exist;
+ }
+//
+// /**
+// * 判断缓存是否失效
+// * @param cachefile
+// * @return
+// */
+// public boolean isCacheDataFailure(String cachefile)
+// {
+// boolean failure = false;
+// File data = getFileStreamPath(cachefile);
+// if(data.exists() && (System.currentTimeMillis() - data.lastModified()) > CACHE_TIME)
+// failure = true;
+// else if(!data.exists())
+// failure = true;
+// return failure;
+// }
+//
+// /**
+// *
+// * 清除app缓存
+// */
+// public void clearAppCache()
+// {
+// //清除webview缓存
+// File file = getCacheDir();
+// if (file != null && file.exists() && file.isDirectory()) {
+// for (File item : file.listFiles()) {
+// item.delete();
+// }
+// file.delete();
+// }
+// deleteDatabase("webview.db");
+// deleteDatabase("webview.db-shm");
+// deleteDatabase("webview.db-wal");
+// deleteDatabase("webviewCache.db");
+// deleteDatabase("webviewCache.db-shm");
+// deleteDatabase("webviewCache.db-wal");
+// //清除数据缓存
+// clearCacheFolder(getFilesDir(),System.currentTimeMillis());
+// clearCacheFolder(getCacheDir(),System.currentTimeMillis());
+// //2.2版本才有将应用缓存转移到sd卡的功能
+// if(isMethodsCompat(Build.VERSION_CODES.FROYO)){
+// clearCacheFolder(getExternalCacheDir(),System.currentTimeMillis());
+// }
+// //清除编辑器保存的临时内容
+// Properties props = getProperties();
+// for(Object key : props.keySet()) {
+// String _key = key.toString();
+// if(_key.startsWith("temp"))
+// removeProperty(_key);
+// }
+// }
+//
+// /**
+// * 清除缓存目录
+// * @param dir 目录
+// * @param numDays 当前系统时间
+// * @return
+// */
+// private int clearCacheFolder(File dir, long curTime) {
+// int deletedFiles = 0;
+// if (dir!= null && dir.isDirectory()) {
+// try {
+// for (File child:dir.listFiles()) {
+// if (child.isDirectory()) {
+// deletedFiles += clearCacheFolder(child, curTime);
+// }
+// if (child.lastModified() < curTime) {
+// if (child.delete()) {
+// deletedFiles++;
+// }
+// }
+// }
+// } catch(Exception e) {
+// e.printStackTrace();
+// }
+// }
+// return deletedFiles;
+// }
+//
+// /**
+// * 将对象保存到内存缓存中
+// * @param key
+// * @param value
+// */
+// public void setMemCache(String key, Object value) {
+// memCacheRegion.put(key, value);
+// }
+//
+// /**
+// * 从内存缓存中获取对象
+// * @param key
+// * @return
+// */
+// public Object getMemCache(String key){
+// return memCacheRegion.get(key);
+// }
+//
+// /**
+// * 保存磁盘缓存
+// * @param key
+// * @param value
+// * @throws IOException
+// */
+// public void setDiskCache(String key, String value) throws IOException {
+// FileOutputStream fos = null;
+// try{
+// fos = openFileOutput("cache_"+key+".data", Context.MODE_PRIVATE);
+// fos.write(value.getBytes());
+// fos.flush();
+// }finally{
+// try {
+// fos.close();
+// } catch (Exception e) {}
+// }
+// }
+//
+// /**
+// * 获取磁盘缓存数据
+// * @param key
+// * @return
+// * @throws IOException
+// */
+// public String getDiskCache(String key) throws IOException {
+// FileInputStream fis = null;
+// try{
+// fis = openFileInput("cache_"+key+".data");
+// byte[] datas = new byte[fis.available()];
+// fis.read(datas);
+// return new String(datas);
+// }finally{
+// try {
+// fis.close();
+// } catch (Exception e) {}
+// }
+// }
+//
+ /**
+ * 保存对象
+ * @param ser
+ * @param file
+ * @throws IOException
+ */
+ public boolean saveObject(Serializable ser, String file) {
+ FileOutputStream fos = null;
+ ObjectOutputStream oos = null;
+ try{
+ fos = openFileOutput(file, MODE_PRIVATE);
+ oos = new ObjectOutputStream(fos);
+ oos.writeObject(ser);
+ oos.flush();
+ return true;
+ }catch(Exception e){
+ e.printStackTrace();
+ return false;
+ }finally{
+ try {
+ oos.close();
+ } catch (Exception e) {}
+ try {
+ fos.close();
+ } catch (Exception e) {}
+ }
+ }
+
+ /**
+ * 读取对象
+ * @param file
+ * @return
+ * @throws IOException
+ */
+ public Serializable readObject(String file){
+ if(!isExistDataCache(file))
+ return null;
+ FileInputStream fis = null;
+ ObjectInputStream ois = null;
+ try{
+ fis = openFileInput(file);
+ ois = new ObjectInputStream(fis);
+ return (Serializable)ois.readObject();
+ }catch(FileNotFoundException e){
+ }catch(Exception e){
+ e.printStackTrace();
+ //反序列化失败 - 删除缓存文件
+ if(e instanceof InvalidClassException){
+ File data = getFileStreamPath(file);
+ data.delete();
+ }
+ }finally{
+ try {
+ ois.close();
+ } catch (Exception e) {}
+ try {
+ fis.close();
+ } catch (Exception e) {}
+ }
+ return null;
+ }
+//
+// public boolean containsProperty(String key){
+// Properties props = getProperties();
+// return props.containsKey(key);
+// }
+//
+// public void setProperties(Properties ps){
+// AppConfig.getAppConfig(this).set(ps);
+// }
+//
+// public Properties getProperties(){
+// return AppConfig.getAppConfig(this).get();
+// }
+//
+ public void setProperty(String key,String value){
+ AppConfig.getAppConfig().set(key, value);
+ }
+
+ public String getProperty(String key){
+ return AppConfig.getAppConfig().get(key);
+ }
+
+
+// public void removeProperty(String...key){
+// AppConfig.getAppConfig(this).remove(key);
+// }
+//
+// /**
+// * 获取内存中保存图片的路径
+// * @return
+// */
+// public String getSaveImagePath() {
+// return saveImagePath;
+// }
+// /**
+// * 设置内存中保存图片的路径
+// * @return
+// */
+// public void setSaveImagePath(String saveImagePath) {
+// this.saveImagePath = saveImagePath;
+// }
+//
+// /**
+// * User-Agent
+// *
+// * @return user-agent
+// */
+// public String getUser_Agent() {
+// String ua = "Android;"
+// + Build.VERSION.RELEASE + ";"
+// + Build.BRAND + "-" + Build.MODEL + ";";
+//
+// ua = ua + getDevicNO() + ";" + System.currentTimeMillis() + ";";
+//
+// return ua;
+// }
+//
+// /**
+// * @return 手机串号 | MAC地址
+// */
+// public String getDevicNO() {
+// if(!TextUtils.isEmpty(getDeviceId())) {
+// return getDeviceId();
+// }
+// if(!TextUtils.isEmpty(getMacAddress())) {
+// return getMacAddress();
+// }
+// return " ";
+// }
+// /**
+// * @return 手机串号:GSM手机的 IMEI 和 CDMA手机的 MEID.
+// */
+// public String getDeviceId() {
+// TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+// if(telephonyManager != null ) {
+// return telephonyManager.getDeviceId();
+// }
+//
+// return null;
+// }
+// /**
+// * @return MAC地址
+// */
+// public String getMacAddress() {
+// // start get mac address
+// WifiManager wifiMan = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+// if (wifiMan != null) {
+// WifiInfo wifiInf = wifiMan.getConnectionInfo();
+// if (wifiInf != null && wifiInf.getMacAddress() != null) {
+// // 48位,如FA:34:7C:6D:E4:D7
+// return wifiInf.getMacAddress();
+// }
+// }
+// return null;
+// }
+
+}
diff --git a/base/src/main/java/com/wlj/base/util/AppException.java b/base/src/main/java/com/wlj/base/util/AppException.java
new file mode 100755
index 0000000..625ab8e
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/AppException.java
@@ -0,0 +1,250 @@
+package com.wlj.base.util;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.net.ConnectException;
+import java.net.SocketException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.Date;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.os.Environment;
+import android.os.Looper;
+import android.widget.Toast;
+
+import com.wlj.base.R;
+import com.wlj.base.web.HttpPost;
+import com.wlj.base.web.BaseURL;
+
+/**
+ * 应用程序异常类:用于捕获异常和提示错误信息
+ * @author liux (http://my.oschina.net/liux)
+ * @version 1.0
+ * @created 2012-3-21
+ */
+public class AppException extends Exception implements UncaughtExceptionHandler{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6128083271862985273L;
+
+ private final static boolean Debug = true;//是否保存错误日志
+
+ /** 定义异常类型 */
+ public final static byte TYPE_NETWORK = 0x01;
+ public final static byte TYPE_SOCKET = 0x02;
+ public final static byte TYPE_HTTP_CODE = 0x03;
+ public final static byte TYPE_HTTP_ERROR= 0x04;
+ public final static byte TYPE_XML = 0x05;
+ public final static byte TYPE_IO = 0x06;
+ public final static byte TYPE_RUN = 0x07;
+ public final static byte TYPE_JSON = 0x08;
+
+ private byte type;
+ private int code;
+
+ /** 系统默认的UncaughtException处理类 */
+ private UncaughtExceptionHandler mDefaultHandler;
+
+ private AppException(){
+ this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+ }
+
+ private AppException(byte type, int code, Exception excp) {
+ super(excp);
+ this.type = type;
+ this.code = code;
+ if(Debug){
+ this.saveErrorLog(excp);
+ }
+ }
+ public int getCode() {
+ return this.code;
+ }
+ public int getType() {
+ return this.type;
+ }
+
+ /**
+ * 保存异常日志
+ * @param excp
+ */
+ public void saveErrorLog(Throwable excp) {
+ String errorlog = "errorlog1.txt";
+ String savePath = "";
+ String logFilePath = "";
+ FileWriter fw = null;
+ PrintWriter pw = null;
+ try {
+ //判断是否挂载了SD卡
+ String storageState = Environment.getExternalStorageState();
+ if(storageState.equals(Environment.MEDIA_MOUNTED)){
+ savePath = AppConfig.getAppConfig().getImagePath()+"/Log/";
+ File file = new File(savePath);
+ if(!file.exists()){
+ file.mkdirs();
+ }
+ logFilePath = savePath + errorlog;
+ }
+ //没有挂载SD卡,无法写文件
+ if(logFilePath == ""){
+ return;
+ }
+ File logFile = new File(logFilePath);
+ if (!logFile.exists()) {
+ logFile.createNewFile();
+ }
+ fw = new FileWriter(logFile,true);
+ pw = new PrintWriter(fw);
+ pw.println("--------------------"+(new Date().toLocaleString())+"---------------------");
+ excp.printStackTrace(pw);
+ pw.close();
+ fw.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }finally{
+ if(pw != null){ pw.close(); }
+ if(fw != null){ try { fw.close(); } catch (IOException e) { }}
+ }
+
+ }
+
+ public static AppException http(int code) {
+ return new AppException(TYPE_HTTP_CODE, code, null);
+ }
+
+ public static AppException http(Exception e) {
+ return new AppException(TYPE_HTTP_ERROR, 0 ,e);
+ }
+
+ public static AppException socket(Exception e) {
+ return new AppException(TYPE_SOCKET, 0 ,e);
+ }
+
+ public static AppException io(Exception e) {
+ if(e instanceof UnknownHostException || e instanceof ConnectException){
+ return new AppException(TYPE_NETWORK, 0, e);
+ }
+ else if(e instanceof IOException){
+ return new AppException(TYPE_IO, 0 ,e);
+ }
+ return run(e);
+ }
+
+ public static AppException xml(Exception e) {
+ return new AppException(TYPE_XML, 0, e);
+ }
+
+ public static AppException json(Exception e) {
+ return new AppException(TYPE_JSON, 0, e);
+ }
+
+ public static AppException network(Exception e) {
+ if(e instanceof UnknownHostException || e instanceof ConnectException){
+ return new AppException(TYPE_NETWORK, 0, e);
+ }
+ else if(e instanceof SocketException){
+ return socket(e);
+ }
+ return http(e);
+ }
+
+ public static AppException run(Exception e) {
+ return new AppException(TYPE_RUN, 0, e);
+ }
+
+ /**
+ * 获取APP异常崩溃处理对象
+ * @return
+ */
+ public static AppException getAppExceptionHandler(){
+ return new AppException();
+ }
+
+ @Override
+ public void uncaughtException(Thread thread, Throwable ex) {
+
+ if(!handleException(ex) && mDefaultHandler != null) {
+ mDefaultHandler.uncaughtException(thread, ex);
+ }
+ }
+ /**
+ * 自定义异常处理:收集错误信息&发送错误报告
+ * @param ex
+ * @return true:处理了该异常信息;否则返回false
+ */
+ private boolean handleException(Throwable ex) {
+ if(ex == null) {
+ return false;
+ }
+
+ if(Debug){
+ this.saveErrorLog(ex);
+ }
+
+ final Context context = AppManager.getAppManager().currentActivity();
+
+ if(context == null) {
+ return false;
+ }
+ final String crashReport = getCrashReport(context, ex);
+ Log.e("dd", crashReport);
+ //显示异常信息&发送报告
+ new Thread() {
+ public void run() {
+ Looper.prepare();
+
+// uploadCrashReport(crashReport);
+// UIHelper.sendAppCrashReport(context, crashReport);
+ Looper.loop();
+ }
+
+ }.start();
+
+ return true;
+ }
+
+ /**
+ * 上传错误日志到服务器
+ */
+// private void uploadCrashReport(String data){
+//
+// try {
+//
+// HttpPost HttpPost = new HttpPost(new URL(BaseURL.upload));
+// HttpPost.addParemeter("date", data);
+//
+// String result = HttpPost.getResult();
+// Log.i(getClass().getSimpleName(), result);
+//
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+//
+// }
+
+ /**
+ * 获取APP崩溃异常报告
+ * @param ex
+ * @return
+ */
+ private String getCrashReport(Context context, Throwable ex) {
+ PackageInfo pinfo = ((AppContext)context.getApplicationContext()).getPackageInfo();
+ StringBuffer exceptionStr = new StringBuffer();
+ exceptionStr.append("Version: "+pinfo.versionName+"("+pinfo.versionCode+")\n");
+ exceptionStr.append("Android: "+android.os.Build.VERSION.RELEASE+"("+android.os.Build.MODEL+")\n");
+ exceptionStr.append("Exception: "+ex.getMessage()+"\n");
+ StackTraceElement[] elements = ex.getStackTrace();
+ ex.printStackTrace();
+ for (int i = 0; i < elements.length; i++) {
+ exceptionStr.append(elements[i].toString()+"\n");
+ }
+ return exceptionStr.toString();
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/AppManager.java b/base/src/main/java/com/wlj/base/util/AppManager.java
new file mode 100755
index 0000000..9b1bd10
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/AppManager.java
@@ -0,0 +1,98 @@
+package com.wlj.base.util;
+
+import java.util.Stack;
+
+import android.app.Activity;
+import android.content.Context;
+
+/**
+ * 应用程序Activity管理类:用于Activity管理和应用程序退出
+ * @author liux (http://my.oschina.net/liux)
+ * @version 1.0
+ * @created 2012-3-21
+ */
+public class AppManager {
+
+ private static Stack activityStack;
+ private static AppManager instance;
+
+ private AppManager(){}
+ /**
+ * 单一实例
+ */
+ public static AppManager getAppManager(){
+ if(instance==null){
+ instance=new AppManager();
+ }
+ return instance;
+ }
+ /**
+ * 添加Activity到堆栈
+ */
+ public void addActivity(Activity activity){
+ if(activityStack==null){
+ activityStack=new Stack();
+ }
+ activityStack.add(activity);
+ }
+ /**
+ * 获取当前Activity(堆栈中最后一个压入的)
+ */
+ public Activity currentActivity(){
+ if(activityStack == null){
+ return null;
+ }
+ Activity activity=activityStack.lastElement();
+ return activity;
+ }
+ /**
+ * 结束当前Activity(堆栈中最后一个压入的)
+ */
+ public void finishActivity(){
+ Activity activity=activityStack.lastElement();
+ finishActivity(activity);
+ }
+ /**
+ * 结束指定的Activity
+ */
+ public void finishActivity(Activity activity){
+ if(activity!=null){
+ activityStack.remove(activity);
+ activity.finish();
+ activity=null;
+ }
+ }
+ /**
+ * 结束指定类名的Activity
+ */
+ public void finishActivity(Class> cls){
+ for (Activity activity : activityStack) {
+ if(activity.getClass().equals(cls) ){
+ finishActivity(activity);
+ }
+ }
+ }
+ /**
+ * 结束所有Activity
+ */
+ public void finishAllActivity(){
+ for (int i = 0, size = activityStack.size(); i < size; i++){
+ if (null != activityStack.get(i)){
+ activityStack.get(i).finish();
+ }
+ }
+ activityStack.clear();
+ }
+ /**
+ * 退出应用程序
+ */
+ public void AppExit(Context context) {
+ try {
+ finishAllActivity();
+// ActivityManager activityMgr= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+// activityMgr.restartPackage(context.getPackageName());
+// activityMgr.killBackgroundProcesses(context.getPackageName());
+ System.exit(0);
+ } catch (Exception e) { }
+ }
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/util/CyptoUtils.java b/base/src/main/java/com/wlj/base/util/CyptoUtils.java
new file mode 100755
index 0000000..017fac6
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/CyptoUtils.java
@@ -0,0 +1,302 @@
+package com.wlj.base.util;
+
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import android.util.Base64;
+
+/**
+ * 加密解密工具包
+ *
+ * @author Winter Lau
+ * @date 2011-12-26
+ */
+public class CyptoUtils {
+
+ public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";
+
+ /**
+ * DES算法,加密
+ *
+ * @param data
+ * 待加密字符串
+ * @param key
+ * 加密私钥,长度不能够小于8位
+ * @return 加密后的字节数组,一般结合Base64编码使用
+ * @throws InvalidAlgorithmParameterException
+ * @throws Exception
+ */
+ public static String encode(String key, String data) {
+ if (data == null)
+ return null;
+ try {
+ DESKeySpec dks = new DESKeySpec(key.getBytes());
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+ // key的长度不能够小于8位字节
+ Key secretKey = keyFactory.generateSecret(dks);
+ Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
+ IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());
+ AlgorithmParameterSpec paramSpec = iv;
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
+ byte[] bytes = cipher.doFinal(data.getBytes());
+ return byte2hex(bytes);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return data;
+ }
+ }
+
+ /**
+ * DES算法,解密
+ *
+ * @param data
+ * 待解密字符串
+ * @param key
+ * 解密私钥,长度不能够小于8位
+ * @return 解密后的字节数组
+ * @throws Exception
+ * 异常
+ */
+ public static String decode(String key, String data) {
+ if (data == null)
+ return null;
+ try {
+ DESKeySpec dks = new DESKeySpec(key.getBytes());
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+ // key的长度不能够小于8位字节
+ Key secretKey = keyFactory.generateSecret(dks);
+ Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
+ IvParameterSpec iv = new IvParameterSpec("12345678".getBytes());
+ AlgorithmParameterSpec paramSpec = iv;
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec);
+ return new String(cipher.doFinal(hex2byte(data.getBytes())));
+ } catch (Exception e) {
+ e.printStackTrace();
+ return data;
+ }
+ }
+
+ /**
+ * 二行制转字符串
+ *
+ * @param b
+ * @return
+ */
+ private static String byte2hex(byte[] b) {
+ StringBuilder hs = new StringBuilder();
+ String stmp;
+ for (int n = 0; b != null && n < b.length; n++) {
+ stmp = Integer.toHexString(b[n] & 0XFF);
+ if (stmp.length() == 1)
+ hs.append('0');
+ hs.append(stmp);
+ }
+ return hs.toString().toUpperCase();
+ }
+
+ private static byte[] hex2byte(byte[] b) {
+ if ((b.length % 2) != 0)
+ throw new IllegalArgumentException();
+ byte[] b2 = new byte[b.length / 2];
+ for (int n = 0; n < b.length; n += 2) {
+ String item = new String(b, n, 2);
+ b2[n / 2] = (byte) Integer.parseInt(item, 16);
+ }
+ return b2;
+ }
+
+ public static String SHA1(String decript) {
+ try {
+ MessageDigest digest = MessageDigest
+ .getInstance("SHA-1");
+ digest.update(decript.getBytes());
+ byte messageDigest[] = digest.digest();
+ // Create Hex String
+ StringBuffer hexString = new StringBuffer();
+ // 字节数组转换为 十六进制 数
+ for (int i = 0; i < messageDigest.length; i++) {
+ String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
+ if (shaHex.length() < 2) {
+ hexString.append(0);
+ }
+ hexString.append(shaHex);
+ }
+ return hexString.toString();
+
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public static String SHA(String decript) {
+ try {
+ MessageDigest digest = MessageDigest
+ .getInstance("SHA");
+ digest.update(decript.getBytes());
+ byte messageDigest[] = digest.digest();
+ // Create Hex String
+ StringBuffer hexString = new StringBuffer();
+ // 字节数组转换为 十六进制 数
+ for (int i = 0; i < messageDigest.length; i++) {
+ String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
+ if (shaHex.length() < 2) {
+ hexString.append(0);
+ }
+ hexString.append(shaHex);
+ }
+ return hexString.toString();
+
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public static String MD5(String input) {
+ try {
+ // 获得MD5摘要算法的 MessageDigest 对象
+ MessageDigest mdInst = MessageDigest.getInstance("MD5");
+ // 使用指定的字节更新摘要
+ mdInst.update(input.getBytes());
+ // 获得密文
+ byte[] md = mdInst.digest();
+ // 把密文转换成十六进制的字符串形式
+ StringBuffer hexString = new StringBuffer();
+ // 字节数组转换为 十六进制 数
+ for (int i = 0; i < md.length; i++) {
+ String shaHex = Integer.toHexString(md[i] & 0xFF);
+ if (shaHex.length() < 2) {
+ hexString.append(0);
+ }
+ hexString.append(shaHex);
+ }
+ return hexString.toString();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * 加密
+ *
+ * @param content
+ * 需要加密的内容
+ * @param password
+ * 加密密码
+ * @return
+ */
+ public static byte[] encryptAES(String content, String password) {
+ try {
+ KeyGenerator kgen = KeyGenerator.getInstance("AES");
+ kgen.init(128, new SecureRandom(password.getBytes()));
+ SecretKey secretKey = kgen.generateKey();
+ byte[] enCodeFormat = secretKey.getEncoded();
+ SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
+ Cipher cipher = Cipher.getInstance("AES");// 创建密码器
+ byte[] byteContent = content.getBytes("utf-8");
+ cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
+ byte[] result = cipher.doFinal(byteContent);
+ return result; // 加密
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (NoSuchPaddingException e) {
+ e.printStackTrace();
+ } catch (InvalidKeyException e) {
+ e.printStackTrace();
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ } catch (IllegalBlockSizeException e) {
+ e.printStackTrace();
+ } catch (BadPaddingException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 解密
+ *
+ * @param content
+ * 待解密内容
+ * @param password
+ * 解密密钥
+ * @return
+ */
+ public static byte[] decryptAES(byte[] content, String password) {
+ try {
+ KeyGenerator kgen = KeyGenerator.getInstance("AES");
+ kgen.init(128, new SecureRandom(password.getBytes()));
+ SecretKey secretKey = kgen.generateKey();
+ byte[] enCodeFormat = secretKey.getEncoded();
+ SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
+ Cipher cipher = Cipher.getInstance("AES");// 创建密码器
+ cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
+ byte[] result = cipher.doFinal(content);
+ return result; // 加密
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (NoSuchPaddingException e) {
+ e.printStackTrace();
+ } catch (InvalidKeyException e) {
+ e.printStackTrace();
+ } catch (IllegalBlockSizeException e) {
+ e.printStackTrace();
+ } catch (BadPaddingException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * BASE64解密
+ *
+ * @param key
+ * @return
+ * @throws Exception
+ */
+ public static String decryptBASE64(String key) {
+
+ try {
+ byte[] k = Base64.decode(key.getBytes("UTF-8"), Base64.DEFAULT);
+ return new String(k,"UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * BASE64加密
+ *
+ * @param key
+ * @return
+ * @throws Exception
+ */
+ public static String encryptBASE64(String key) {
+
+ try {
+ return new String(Base64.encode(key.getBytes("UTF-8"), Base64.DEFAULT),"UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/DpAndPx.java b/base/src/main/java/com/wlj/base/util/DpAndPx.java
new file mode 100755
index 0000000..1771db3
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/DpAndPx.java
@@ -0,0 +1,29 @@
+package com.wlj.base.util;
+
+import android.content.Context;
+import android.util.TypedValue;
+/**
+ * dp与px互转
+ * @author wlj
+ *
+ */
+public class DpAndPx {
+
+ public static int dpToPx(Context context, float dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
+ }
+
+ /**
+ * 像素转化dip
+ * @param context
+ * @param pxValue
+ * @return
+ */
+ public static int px2dip(Context context, float pxValue){
+
+ final float scale = context.getResources().getDisplayMetrics().density;
+
+ return (int)(pxValue / scale + 0.5f);
+
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/ExecutorServices.java b/base/src/main/java/com/wlj/base/util/ExecutorServices.java
new file mode 100755
index 0000000..b1d3c8a
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/ExecutorServices.java
@@ -0,0 +1,22 @@
+package com.wlj.base.util;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * 线程池
+ * @created 2012-3-21
+ */
+public class ExecutorServices {
+
+ private static ExecutorService pool;
+
+ public static ExecutorService getExecutorService() {
+
+ if (pool == null) {
+
+ pool = Executors.newFixedThreadPool(10);
+ }
+ return pool;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/GetResourceImage.java b/base/src/main/java/com/wlj/base/util/GetResourceImage.java
new file mode 100755
index 0000000..7856b05
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/GetResourceImage.java
@@ -0,0 +1,96 @@
+package com.wlj.base.util;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+
+public class GetResourceImage {
+
+ public static Bitmap get(Context context,int resId){
+
+ BitmapFactory.Options opt = new BitmapFactory.Options();
+
+ opt.inPreferredConfig = Bitmap.Config.RGB_565;
+
+ opt.inPurgeable = true;
+
+ opt.inInputShareable = true;
+
+ //获取资源图片
+ InputStream is = context.getResources().openRawResource(resId);
+
+ Bitmap bitmap = null;
+
+ bitmap = BitmapFactory.decodeStream(is,null, opt);
+
+ try {
+ is.close();
+ } catch (IOException e) {
+ if(Log.LOG)e.printStackTrace();
+ }
+ return bitmap;
+ }
+ public static Drawable getDrawable(Context context,int resId){
+ BitmapFactory.Options opt = new BitmapFactory.Options();
+
+ opt.inPreferredConfig = Bitmap.Config.RGB_565;
+
+ opt.inPurgeable = true;
+
+ opt.inInputShareable = true;
+
+ //获取资源图片
+ InputStream is = context.getResources().openRawResource(resId);
+
+ Drawable drawable = Drawable.createFromStream(is, "src");
+
+ try {
+ is.close();
+ } catch (IOException e) {
+ if(Log.LOG)e.printStackTrace();
+ }
+ return drawable;
+
+ }
+
+ //没明白为什么不可以
+// public static Drawable getDrawable2(Context context,int resId){
+//
+// BitmapFactory.Options opt = new BitmapFactory.Options();
+//
+// opt.inPreferredConfig = Bitmap.Config.RGB_565;
+//
+// opt.inPurgeable = true;
+//
+// opt.inInputShareable = true;
+//
+// //获取资源图片
+//
+// AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
+//
+// Bitmap bitmap = null;
+//// FileInputStream in = null;
+// try {
+// FileDescriptor fileDescriptor = afd.getFileDescriptor();
+//// in = afd.createInputStream();
+// bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor,null, opt);
+// }finally{
+// try {
+//// in.close();
+// afd.close();
+//
+// } catch (IOException e) {
+// if(Log.LOG)e.printStackTrace();
+// }
+// }
+// return new BitmapDrawable(context.getResources(),bitmap);
+// }
+}
diff --git a/base/src/main/java/com/wlj/base/util/GoToHelp.java b/base/src/main/java/com/wlj/base/util/GoToHelp.java
new file mode 100644
index 0000000..4acd20f
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/GoToHelp.java
@@ -0,0 +1,20 @@
+package com.wlj.base.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Created by wlj on 2016/10/28.
+ */
+
+public class GoToHelp {
+
+
+ public static Intent go(Activity mContent, Class> cls) {
+ Intent intent = new Intent(mContent, cls);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mContent.startActivity(intent);
+ return intent;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/ListUtils.java b/base/src/main/java/com/wlj/base/util/ListUtils.java
new file mode 100755
index 0000000..91575db
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/ListUtils.java
@@ -0,0 +1,202 @@
+package com.wlj.base.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.text.TextUtils;
+
+/**
+ * List Utils
+ *
+ * @author Trinea 2011-7-22
+ */
+public class ListUtils {
+
+ /** default join separator **/
+ public static final String DEFAULT_JOIN_SEPARATOR = ",";
+
+ private ListUtils() {
+ throw new AssertionError();
+ }
+
+ /**
+ * get size of list
+ *
+ *
+ * getSize(null) = 0;
+ * getSize({}) = 0;
+ * getSize({1}) = 1;
+ *
+ *
+ * @param
+ * @param sourceList
+ * @return if list is null or empty, return 0, else return {@link List#size()}.
+ */
+ public static int getSize(List sourceList) {
+ return sourceList == null ? 0 : sourceList.size();
+ }
+
+ /**
+ * is null or its size is 0
+ *
+ *
+ * isEmpty(null) = true;
+ * isEmpty({}) = true;
+ * isEmpty({1}) = false;
+ *
+ *
+ * @param
+ * @param sourceList
+ * @return if list is null or its size is 0, return true, else return false.
+ */
+ public static boolean isEmpty(List sourceList) {
+ return (sourceList == null || sourceList.size() == 0);
+ }
+
+ /**
+ * join list to string, separator is ","
+ *
+ *
+ * join(null) = "";
+ * join({}) = "";
+ * join({a,b}) = "a,b";
+ *
+ *
+ * @param list
+ * @return join list to string, separator is ",". if list is empty, return ""
+ */
+ public static String join(List list) {
+ return join(list, DEFAULT_JOIN_SEPARATOR);
+ }
+
+ /**
+ * join list to string
+ *
+ *
+ * join(null, '#') = "";
+ * join({}, '#') = "";
+ * join({a,b,c}, ' ') = "abc";
+ * join({a,b,c}, '#') = "a#b#c";
+ *
+ *
+ * @param list
+ * @param separator
+ * @return join list to string. if list is empty, return ""
+ */
+ public static String join(List list, char separator) {
+ return join(list, new String(new char[] {separator}));
+ }
+
+ /**
+ * join list to string. if separator is null, use {@link #DEFAULT_JOIN_SEPARATOR}
+ *
+ *
+ * join(null, "#") = "";
+ * join({}, "#$") = "";
+ * join({a,b,c}, null) = "a,b,c";
+ * join({a,b,c}, "") = "abc";
+ * join({a,b,c}, "#") = "a#b#c";
+ * join({a,b,c}, "#$") = "a#$b#$c";
+ *
+ *
+ * @param list
+ * @param separator
+ * @return join list to string with separator. if list is empty, return ""
+ */
+ public static String join(List list, String separator) {
+ return list == null ? "" : TextUtils.join(separator, list);
+ }
+
+ /**
+ * add distinct entry to list
+ *
+ * @param
+ * @param sourceList
+ * @param entry
+ * @return if entry already exist in sourceList, return false, else add it and return true.
+ */
+ public static boolean addDistinctEntry(List sourceList, V entry) {
+ return (sourceList != null && !sourceList.contains(entry)) ? sourceList.add(entry) : false;
+ }
+
+ /**
+ * add all distinct entry to list1 from list2
+ *
+ * @param
+ * @param sourceList
+ * @param entryList
+ * @return the count of entries be added
+ */
+ public static int addDistinctList(List sourceList, List entryList) {
+ if (sourceList == null || isEmpty(entryList)) {
+ return 0;
+ }
+
+ int sourceCount = sourceList.size();
+ for (V entry : entryList) {
+ if (!sourceList.contains(entry)) {
+ sourceList.add(entry);
+ }
+ }
+ return sourceList.size() - sourceCount;
+ }
+
+ /**
+ * remove duplicate entries in list
+ *
+ * @param
+ * @param sourceList
+ * @return the count of entries be removed
+ */
+ public static int distinctList(List sourceList) {
+ if (isEmpty(sourceList)) {
+ return 0;
+ }
+
+ int sourceCount = sourceList.size();
+ int sourceListSize = sourceList.size();
+ for (int i = 0; i < sourceListSize; i++) {
+ for (int j = (i + 1); j < sourceListSize; j++) {
+ if (sourceList.get(i).equals(sourceList.get(j))) {
+ sourceList.remove(j);
+ sourceListSize = sourceList.size();
+ j--;
+ }
+ }
+ }
+ return sourceCount - sourceList.size();
+ }
+
+ /**
+ * add not null entry to list
+ *
+ * @param sourceList
+ * @param value
+ * @return
+ * if sourceList is null, return false
+ * if value is null, return false
+ * return {@link List#add(Object)}
+ *
+ */
+ public static boolean addListNotNullValue(List sourceList, V value) {
+ return (sourceList != null && value != null) ? sourceList.add(value) : false;
+ }
+ /**
+ * invert list
+ *
+ * @param
+ * @param sourceList
+ * @return
+ */
+ public static List invertList(List sourceList) {
+ if (isEmpty(sourceList)) {
+ return sourceList;
+ }
+
+ List invertList = new ArrayList(sourceList.size());
+ for (int i = sourceList.size() - 1; i >= 0; i--) {
+ invertList.add(sourceList.get(i));
+ }
+ return invertList;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/Log.java b/base/src/main/java/com/wlj/base/util/Log.java
new file mode 100755
index 0000000..7b00dae
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/Log.java
@@ -0,0 +1,26 @@
+package com.wlj.base.util;
+
+public class Log {
+ public static final boolean LOG = true;
+ public static final boolean TEST = true;
+
+ public static void i(String tag, String string) {
+ if (LOG)android.util.Log.i(tag, string);
+ }
+
+ public static void e(String tag, String string) {
+ if (LOG)android.util.Log.e(tag, string);
+ }
+
+ public static void d(String tag, String string) {
+ if (LOG)android.util.Log.d(tag, string);
+ }
+
+ public static void v(String tag, String string) {
+ if (LOG)android.util.Log.v(tag, string);
+ }
+
+ public static void w(String tag, String string) {
+ if (LOG)android.util.Log.w(tag, string);
+ }
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/util/MathUtil.java b/base/src/main/java/com/wlj/base/util/MathUtil.java
new file mode 100755
index 0000000..2c7766d
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/MathUtil.java
@@ -0,0 +1,211 @@
+package com.wlj.base.util;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+
+public class MathUtil {
+
+ public static float parseFloat(String s){
+ if(s==null){
+ return 0f;
+ }
+ Float r = null;
+ try{
+ r = Float.parseFloat(s);
+ }catch(NumberFormatException e){
+ r=0f;
+ }
+ return r;
+ }
+ public static double parseDouble(String s){
+ if(s==null){
+ return 0d;
+ }
+ double r = 0d;
+ try{
+ r = Double.parseDouble(s);
+ }catch(NumberFormatException e){
+ r=0d;
+ }
+ return r;
+ }
+ public static long parseLong(String s){
+ Long r = null;
+ try{
+ r = Long.parseLong(s);
+ }catch(NumberFormatException e){
+ r=0l;
+ }
+ return r;
+ }
+ /**
+ * return null if throw NumberFormatException else return number of this string
+ * @param s
+ * @return
+ */
+ public static int parseInteger(String s){
+ Integer r = null;
+ try{
+ r = Integer.parseInt(s);
+ }catch(NumberFormatException e){
+ r=0;
+ }
+ return r;
+ }
+ /**
+ * 去掉浮点数最后的0 比如浮点数 1024 转换为string 后就是 1024.0 了 需要把他转换成 1024 否者接口的money 如果传入1024.0 就会出现签名
+ * 验证失败 必须整成1024
+ * @param str
+ * @return
+ */
+ public static String trimShu(String str) {
+ if (str.indexOf(".") != -1 && str.charAt(str.length() - 1) == '0') {
+ return trimShu(str.substring(0, str.length() - 1));
+ } else {
+ return str.charAt(str.length() - 1) == '.' ? str.substring(0, str.length() - 1) : str;
+ }
+
+ }
+
+ /**
+ * obj1 + obj2
+ * @param obj1
+ * @param obj2
+ * @return 相加结果
+ */
+ public static BigDecimal add(Object obj1,Object obj2){
+ if(obj1 == null){
+ obj1 = "0";
+ }
+ if(obj2 == null){
+ obj2 = "0";
+ }
+ BigDecimal bd1 = null;
+ BigDecimal bd2 = null;
+ if(obj1 instanceof BigDecimal){
+ bd1 = (BigDecimal)obj1;
+ }else{
+ bd1 = new BigDecimal(obj1.toString());
+ }
+ if(obj2 instanceof BigDecimal){
+ bd2 = (BigDecimal)obj2;
+ }else{
+ bd2 = new BigDecimal(obj2.toString());
+ }
+ return bd1.add(bd2);
+ }
+ /**
+ * obj1 - obj2
+ * @param obj1
+ * @param obj2
+ * @return 相减结果
+ */
+ public static BigDecimal subtract(Object obj1,Object obj2){
+ if(obj1 == null){
+ obj1 = "0";
+ }
+ if(obj2 == null){
+ obj2 = "0";
+ }
+
+ BigDecimal bd1 = null;
+ BigDecimal bd2 = null;
+ if(obj1 instanceof BigDecimal){
+ bd1 = (BigDecimal)obj1;
+ }else{
+ bd1 = new BigDecimal(obj1.toString());
+ }
+ if(obj2 instanceof BigDecimal){
+ bd2 = (BigDecimal)obj2;
+ }else{
+ bd2 = new BigDecimal(obj2.toString());
+ }
+ return bd1.subtract(bd2);
+ }
+ /**
+ * obj1 * obj2
+ * @param obj1
+ * @param obj2
+ * @return 相乘结果
+ */
+ public static BigDecimal multiply(Object obj1,Object obj2){
+ if(obj1 == null){
+ obj1 = "0";
+ }
+ if(obj2 == null){
+ obj2 = "0";
+ }
+
+ BigDecimal bd1 = null;
+ BigDecimal bd2 = null;
+ if(obj1 instanceof BigDecimal){
+ bd1 = (BigDecimal)obj1;
+ }else{
+ bd1 = new BigDecimal(obj1.toString());
+ }
+ if(obj2 instanceof BigDecimal){
+ bd2 = (BigDecimal)obj2;
+ }else{
+ bd2 = new BigDecimal(obj2.toString());
+ }
+ return bd1.multiply(bd2);
+ }
+ /**
+ * obj1 / obj2
+ * @param obj1
+ * @param obj2
+ * @return 相除保留4位 4舍5入
+ */
+ public static BigDecimal divide(Object obj1,Object obj2){
+ if(obj1 == null){
+ obj1 = "0";
+ }
+ if(obj2 == null){
+ obj2 = "0";
+ }
+
+ BigDecimal bd1 = null;
+ BigDecimal bd2 = null;
+ if(obj1 instanceof BigDecimal){
+ bd1 = (BigDecimal)obj1;
+ }else{
+ bd1 = new BigDecimal(obj1.toString());
+ }
+ if(obj2 instanceof BigDecimal){
+ bd2 = (BigDecimal)obj2;
+ }else{
+ bd2 = new BigDecimal(obj2.toString());
+ }
+ return bd1.divide(bd2,8,RoundingMode.HALF_EVEN);
+ }
+
+ /**
+ * obj1 / obj2
+ * @param obj1
+ * @param obj2
+ * @return 舍弃 余数
+ */
+ public static BigDecimal divideDwon(Object obj1,Object obj2){
+ if(obj1 == null){
+ obj1 = "0";
+ }
+ if(obj2 == null){
+ obj2 = "0";
+ }
+
+ BigDecimal bd1 = null;
+ BigDecimal bd2 = null;
+ if(obj1 instanceof BigDecimal){
+ bd1 = (BigDecimal)obj1;
+ }else{
+ bd1 = new BigDecimal(obj1.toString());
+ }
+ if(obj2 instanceof BigDecimal){
+ bd2 = (BigDecimal)obj2;
+ }else{
+ bd2 = new BigDecimal(obj2.toString());
+ }
+ return bd1.divide(bd2,0,RoundingMode.DOWN);
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/RequestException.java b/base/src/main/java/com/wlj/base/util/RequestException.java
new file mode 100755
index 0000000..f71ab00
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/RequestException.java
@@ -0,0 +1,27 @@
+package com.wlj.base.util;
+
+public class RequestException extends Exception{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1357697966549014612L;
+
+ public RequestException() {
+ super();
+ }
+
+ public RequestException(String detailMessage, Throwable throwable) {
+ super(detailMessage, throwable);
+ }
+
+ public RequestException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ public RequestException(Throwable throwable) {
+ super(throwable);
+ }
+
+
+}
diff --git a/base/src/main/java/com/wlj/base/util/StatusBarHeight.java b/base/src/main/java/com/wlj/base/util/StatusBarHeight.java
new file mode 100755
index 0000000..aedad13
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/StatusBarHeight.java
@@ -0,0 +1,37 @@
+package com.wlj.base.util;
+
+import java.lang.reflect.Field;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+
+/**
+ * 获取通知栏高度
+ * @author wlj
+ *
+ */
+public class StatusBarHeight {
+
+ public static int getStatusBarHeight() {
+ return Resources.getSystem().getDimensionPixelSize(
+ Resources.getSystem().getIdentifier("status_bar_height", "dimen", "android"));
+ }
+
+ public static int getStatusBarHeight3(Context context){
+ Class> c = null;
+ Object obj = null;
+ Field field = null;
+ int x = 0, statusBarHeight = 0;
+ try {
+ c = Class.forName("com.android.internal.R$dimen");
+ obj = c.newInstance();
+ field = c.getField("status_bar_height");
+ x = Integer.parseInt(field.get(obj).toString());
+ statusBarHeight = context.getResources().getDimensionPixelSize(x);
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ return statusBarHeight;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/StringUtils.java b/base/src/main/java/com/wlj/base/util/StringUtils.java
new file mode 100755
index 0000000..c062848
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/StringUtils.java
@@ -0,0 +1,330 @@
+package com.wlj.base.util;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.regex.Pattern;
+
+/**
+ * 字符串操作工具包
+ *
+ * @author liux (http://my.oschina.net/liux)
+ * @version 1.0
+ * @created 2012-3-21
+ */
+public class StringUtils {
+ private final static Pattern emailer = Pattern.compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*");
+ // private final static SimpleDateFormat dateFormater = new
+ // SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ // private final static SimpleDateFormat dateFormater2 = new
+ // SimpleDateFormat("yyyy-MM-dd");
+
+ private final static ThreadLocal dateFormater = new ThreadLocal() {
+ @Override
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+ };
+
+ private final static ThreadLocal dateFormater2 = new ThreadLocal() {
+ @Override
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd");
+ }
+ };
+
+
+ public static long getTime(String time) {
+
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ try {
+ return format.parse(time).getTime();
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+ /**
+ *
+ * @param time 2014/10/4 16:02:46
+ * @return
+ */
+ public static long getTime2(String time) {
+
+ SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+ try {
+ return format.parse(time).getTime();
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ /**
+ *
+ * @param time
+ * @return yy-MM-dd HH:mm格式时间
+ */
+ public static String getTime(long time) {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ return format.format(new Date(time));
+ }
+
+ /**
+ *
+ * @param time
+ * @param type
+ * @return
+ */
+ public static String getTime(long time,String type) {
+ SimpleDateFormat format = new SimpleDateFormat(type);
+ return format.format(new Date(time));
+ }
+
+ /**
+ * 将字符串转为日期类型
+ *
+ * @param sdate
+ * @return
+ */
+ public static Date toDate(String sdate) {
+ try {
+ return dateFormater.get().parse(sdate);
+ } catch (ParseException e) {
+ AppException.run(e);
+ return null;
+ }
+ }
+
+ /**
+ * 以友好的方式显示时间
+ *
+ * @param sdate
+ * @return
+ */
+ public static String friendly_time(String sdate) {
+ Date time = null;
+ if (TimeZoneUtil.isInEasternEightZones()) {
+ time = toDate(sdate);
+ } else {
+ time = TimeZoneUtil.transformTime(toDate(sdate),
+ TimeZone.getTimeZone("GMT+08"), TimeZone.getDefault());
+ }
+ if (time == null) {
+ return "Unknown";
+ }
+ String ftime = "";
+ Calendar cal = Calendar.getInstance();
+
+ // 判断是否是同一天
+ String curDate = dateFormater2.get().format(cal.getTime());
+ String paramDate = dateFormater2.get().format(time);
+ if (curDate.equals(paramDate)) {
+ int hour = (int) ((cal.getTimeInMillis() - time.getTime()) / 3600000);
+ if (hour == 0)
+ ftime = Math.max(
+ (cal.getTimeInMillis() - time.getTime()) / 60000, 1)
+ + "分钟前";
+ else
+ ftime = hour + "小时前";
+ return ftime;
+ }
+
+ long lt = time.getTime() / 86400000;
+ long ct = cal.getTimeInMillis() / 86400000;
+ int days = (int) (ct - lt);
+ if (days == 0) {
+ int hour = (int) ((cal.getTimeInMillis() - time.getTime()) / 3600000);
+ if (hour == 0)
+ ftime = Math.max(
+ (cal.getTimeInMillis() - time.getTime()) / 60000, 1)
+ + "分钟前";
+ else
+ ftime = hour + "小时前";
+ } else if (days == 1) {
+ ftime = "昨天";
+ } else if (days == 2) {
+ ftime = "前天";
+ } else if (days > 2 && days <= 10) {
+ ftime = days + "天前";
+ } else if (days > 10) {
+ ftime = dateFormater2.get().format(time);
+ }
+ return ftime;
+ }
+
+ /**
+ * 判断给定字符串时间是否为今日
+ *
+ * @param sdate
+ * @return boolean
+ */
+ public static boolean isToday(String sdate) {
+ boolean b = false;
+ Date time = toDate(sdate);
+ Date today = new Date();
+ if (time != null) {
+ String nowDate = dateFormater2.get().format(today);
+ String timeDate = dateFormater2.get().format(time);
+ if (nowDate.equals(timeDate)) {
+ b = true;
+ }
+ }
+ return b;
+ }
+
+ /**
+ * 返回long类型的今天的日期
+ *
+ * @return
+ */
+ public static long getToday() {
+ Calendar cal = Calendar.getInstance();
+ String curDate = dateFormater2.get().format(cal.getTime());
+ curDate = curDate.replace("-", "");
+ return Long.parseLong(curDate);
+ }
+
+ /**
+ * 判断给定字符串是否空白串。 空白串是指由空格、制表符、回车符、换行符组成的字符串 若输入字符串为null或空字符串,返回true
+ *
+ * @param input
+ * @return boolean
+ */
+ public static boolean isEmpty(String input) {
+ if (input == null || "".equals(input))
+ return true;
+
+ for (int i = 0; i < input.length(); i++) {
+ char c = input.charAt(i);
+ if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 判断是不是一个合法的电子邮件地址
+ *
+ * @param email
+ * @return
+ */
+ public static boolean isEmail(String email) {
+ if (email == null || email.trim().length() == 0)
+ return false;
+ return emailer.matcher(email).matches();
+ }
+
+ /**
+ * 字符串转整数
+ *
+ * @param str
+ * @param defValue
+ * @return
+ */
+ public static int toInt(String str, int defValue) {
+ try {
+ return Integer.parseInt(str);
+ } catch (Exception e) {
+ }
+ return defValue;
+ }
+
+ /**
+ * 对象转整数
+ *
+ * @param obj
+ * @return 转换异常返回 0
+ */
+ public static int toInt(Object obj) {
+ if (obj == null)
+ return 0;
+ return toInt(obj.toString(), 0);
+ }
+
+ /**
+ * 对象转整数
+ *
+ * @param obj
+ * @return 转换异常返回 0
+ */
+ public static long toLong(String obj) {
+ try {
+ return Long.parseLong(obj);
+ } catch (Exception e) {
+ }
+ return 0;
+ }
+
+ /**
+ * 字符串转布尔值
+ *
+ * @param b
+ * @return 转换异常返回 false
+ */
+ public static boolean toBool(String b) {
+ try {
+ return Boolean.parseBoolean(b);
+ } catch (Exception e) {
+ }
+ return false;
+ }
+
+ /**
+ * 将一个InputStream流转换成字符串
+ *
+ * @param is
+ * @return
+ */
+ public static String toConvertString(InputStream is) {
+ StringBuffer res = new StringBuffer();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader read = new BufferedReader(isr);
+ try {
+ String line;
+ line = read.readLine();
+ while (line != null) {
+ res.append(line);
+ line = read.readLine();
+ }
+ } catch (IOException e) {
+ AppException.io(e);
+ e.printStackTrace();
+ } finally {
+ try {
+ if (null != isr) {
+ isr.close();
+ isr.close();
+ }
+ if (null != read) {
+ read.close();
+ read = null;
+ }
+ if (null != is) {
+ is.close();
+ is = null;
+ }
+ } catch (IOException e) {
+ AppException.io(e);
+ }
+ }
+ return res.toString();
+ }
+
+ public static boolean isnull(String str){
+ if(str == null || "".equals(str)){
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/SyncImageLoader.java b/base/src/main/java/com/wlj/base/util/SyncImageLoader.java
new file mode 100755
index 0000000..6bbe24e
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/SyncImageLoader.java
@@ -0,0 +1,187 @@
+package com.wlj.base.util;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.SoftReference;
+import java.net.URL;
+import java.util.HashMap;
+
+import com.wlj.base.util.img.ImageGetForHttp;
+
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Environment;
+import android.os.Handler;
+
+/**
+ * 异步加载图片
+ * @author wlj
+ *
+ */
+public class SyncImageLoader {
+
+ private Object lock = new Object();
+
+ private boolean mAllowLoad = true;
+
+ private boolean firstLoad = true;
+
+ private int mStartLoadLimit = 0;
+
+ private int mStopLoadLimit = 0;
+
+ final Handler handler = new Handler();
+
+ private HashMap> imageCache = new HashMap>();
+
+ public interface OnImageLoadListener {
+ public void onImageLoad(Integer t, Drawable drawable);
+ public void onError(Integer t);
+ }
+
+ public void setLoadLimit(int startLoadLimit,int stopLoadLimit){
+ if(startLoadLimit > stopLoadLimit){
+ return;
+ }
+ mStartLoadLimit = startLoadLimit;
+ mStopLoadLimit = stopLoadLimit;
+ }
+
+ public void restore(){
+ mAllowLoad = true;
+ firstLoad = true;
+ }
+
+ public void lock(){
+ mAllowLoad = false;
+ firstLoad = false;
+ }
+
+ public void unlock(){
+ mAllowLoad = true;
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ }
+ /**
+ *
+ * @param t mStartLoadLimit、mStopLoadLimit,listener会返回次参数
+ * @param imageUrl url
+ * @param listener 图片加载完后的返回
+ * @param author1 图片名称
+ */
+ public void loadImage(Integer t, String imageUrl,OnImageLoadListener listener,String author1) {
+ final OnImageLoadListener mListener = listener;
+ final String mImageUrl = imageUrl;
+ final Integer mt = t;
+ final String author = author1;
+
+ ExecutorServices.getExecutorService().execute(new Runnable() {
+
+ @Override
+ public void run() {
+ if(!mAllowLoad){
+ synchronized (lock) {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ if(mAllowLoad && firstLoad){
+ loadImage(mImageUrl, mt, mListener,author);
+ }
+
+ if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit){
+ loadImage(mImageUrl, mt, mListener,author);
+ }
+ }
+
+ });
+ }
+
+ private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener,final String author){
+
+ if (imageCache.containsKey(mImageUrl)) {
+ System.out.println("drawable");
+ SoftReference softReference = imageCache.get(mImageUrl);
+ final Drawable d = softReference.get();
+ if (d != null) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mAllowLoad){
+ mListener.onImageLoad(mt, d);
+ }
+ }
+ });
+ return;
+ }
+ }
+ try {
+ final Drawable d = loadImageFromUrl(mImageUrl,author);
+ if(d != null){
+ imageCache.put(mImageUrl, new SoftReference(d));
+ }
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mAllowLoad){
+ mListener.onImageLoad(mt, d);
+ }
+ }
+ });
+ } catch (IOException e) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ mListener.onError(mt);
+ }
+ });
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ *
+ * @param url 图片url
+ * @param author 图片名称
+ * @return Drawable
+ * @throws IOException
+ */
+ public static Drawable loadImageFromUrl(String url,String author) throws IOException {
+ //是否SD卡可用
+ if( Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
+ //检查是或有保存图片的文件夹,没有就穿件一个
+ String FileUrl = AppConfig.getAppConfig().getImagePath();
+ File folder = new File(FileUrl);
+ if(!folder.exists()){
+ folder.mkdir();
+ }
+ File f = new File(FileUrl+author+".jpg");
+ //SD卡中是否有该文件,有则直接读取返回
+ if(f.exists()){
+ FileInputStream fis = new FileInputStream(f);
+ Drawable d = Drawable.createFromStream(fis, "src");
+ return d;
+ }
+ //没有的话则去连接下载,并写入到SD卡中
+ Bitmap bitmap = ImageGetForHttp.downloadBitmap(url);
+
+ return new BitmapDrawable(null,bitmap);
+ }
+ //SD卡不可用则直接加载使用
+ else{
+ URL m = new URL(url);
+ InputStream i = (InputStream) m.getContent();
+ Drawable d = Drawable.createFromStream(i, "src");
+ return d;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/util/TimeZoneUtil.java b/base/src/main/java/com/wlj/base/util/TimeZoneUtil.java
new file mode 100755
index 0000000..5992ca1
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/TimeZoneUtil.java
@@ -0,0 +1,46 @@
+package com.wlj.base.util;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * 不同时区对应的时间处理工具类
+ *
+ * @author HuangWenwei
+ *
+ * @date 2014年7月31日
+ */
+public class TimeZoneUtil {
+
+ /**
+ * 判断用户的设备时区是否为东八区(中国) 2014年7月31日
+ *
+ * @return
+ */
+ public static boolean isInEasternEightZones() {
+ boolean defaultVaule = true;
+ if (TimeZone.getDefault() == TimeZone.getTimeZone("GMT+08"))
+ defaultVaule = true;
+ else
+ defaultVaule = false;
+ return defaultVaule;
+ }
+
+ /**
+ * 根据不同时区,转换时间 2014年7月31日
+ *
+ * @param time
+ * @return
+ */
+ public static Date transformTime(Date date, TimeZone oldZone,
+ TimeZone newZone) {
+ Date finalDate = null;
+ if (date != null) {
+ int timeOffset = oldZone.getOffset(date.getTime())
+ - newZone.getOffset(date.getTime());
+ finalDate = new Date(date.getTime() - timeOffset);
+ }
+ return finalDate;
+
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/UIHelper.java b/base/src/main/java/com/wlj/base/util/UIHelper.java
new file mode 100755
index 0000000..8b8cf0a
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/UIHelper.java
@@ -0,0 +1,143 @@
+package com.wlj.base.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+
+import com.wlj.base.R;
+import com.wlj.base.util.Log;
+
+import android.graphics.drawable.ColorDrawable;
+import android.os.Handler;
+import android.provider.Settings;
+import android.sax.StartElementListener;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.Toast;
+
+public class UIHelper {
+
+ public final static int LISTVIEW_ACTION_INIT = 51;
+ public final static int LISTVIEW_ACTION_REFRESH = 52;
+ public final static int LISTVIEW_ACTION_SCROLL = 53;
+ public final static int LISTVIEW_ACTION_CHANGE_CATALOG = 54;
+
+ private static AlertDialog Progressbardlg;
+
+ /**
+ * 弹出Toast消息
+ *
+ * @param msg
+ */
+ public static void toastMessage(Context cont, String msg) {
+ Toast.makeText(cont, msg, Toast.LENGTH_SHORT).show();
+ }
+
+ public static void toastMessage(Context cont, int msg) {
+ Toast.makeText(cont, msg, Toast.LENGTH_SHORT).show();
+ }
+
+ public static void toastMessage(Context cont, String msg, int time) {
+ Toast.makeText(cont, msg, time).show();
+ }
+
+ private static ProgressDialog progressDialog;
+ static long starttime;
+
+ public static void loading(String str, Activity mContext) {
+ starttime = System.currentTimeMillis();
+ progressDialog = ProgressDialog.show(mContext, "提示", str);
+ }
+
+ public static void loadingCir(Activity context) {
+ progressDialog = new ProgressDialog(context);
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ progressDialog.show();
+ }
+
+ public static void loadingClose() {
+ if (progressDialog != null && progressDialog.isShowing())
+ progressDialog.dismiss();
+ }
+
+ /**
+ * 点击返回监听事件
+ *
+ * @param activity
+ * @return
+ */
+ public static OnClickListener finish(final Activity activity) {
+ return new OnClickListener() {
+ public void onClick(View v) {
+ activity.finish();
+ }
+ };
+ }
+
+ /**
+ * 打开gps提示框
+ *
+ * @param cont
+ * @param crashReport
+ */
+ public static void GpsOpenTip(final Context cont, final String crashReport) {
+
+ Builder builder = new Builder(cont);
+ builder.setIcon(android.R.drawable.ic_dialog_info);
+ builder.setTitle(R.string.app_tipr);
+ builder.setMessage(crashReport);
+ builder.setPositiveButton("幸福地开启",
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ cont.startActivity(intent);
+ dialog.dismiss();
+ }
+ });
+ builder.setNegativeButton("残忍地拒绝",
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ });
+ builder.show();
+ }
+
+
+ public static void dialog(Context cont, String message, DialogInterface.OnClickListener positivelistener, DialogInterface.OnClickListener negativelistener) {
+
+ Builder builder = new Builder(cont);
+ builder.setIcon(android.R.drawable.ic_dialog_info);
+ builder.setTitle(R.string.app_tipr);
+ builder.setMessage(message);
+ builder.setPositiveButton("确认", positivelistener);
+ builder.setNegativeButton("取消", negativelistener);
+ builder.show();
+ }
+
+ public static void showProgressbar(Activity paramActivity, DialogInterface.OnCancelListener paramOnCancelListener) {
+ closeProgressbar();
+
+ Progressbardlg = new AlertDialog.Builder(paramActivity).create();
+ Window localWindow = Progressbardlg.getWindow();
+ localWindow.setBackgroundDrawable(new ColorDrawable(0));
+ Progressbardlg.show();
+ localWindow.setContentView(R.layout.progressbar);
+ Progressbardlg.setOnCancelListener(paramOnCancelListener);
+ }
+
+ public static void closeProgressbar() {
+ if(Progressbardlg != null) {
+ Progressbardlg.dismiss();
+ Progressbardlg = null;
+ }
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/util/img/BitmapUtil.java b/base/src/main/java/com/wlj/base/util/img/BitmapUtil.java
new file mode 100755
index 0000000..b2bbed8
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/img/BitmapUtil.java
@@ -0,0 +1,180 @@
+package com.wlj.base.util.img;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.wlj.base.util.Log;
+
+import android.annotation.SuppressLint;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.media.ExifInterface;
+import android.os.Build;
+import android.util.Base64;
+import android.widget.ImageView;
+
+/**
+ *
+ * @author wlj
+ *
+ */
+public class BitmapUtil {
+
+ private static BitmapUtil imageUtil;
+
+ public static BitmapUtil getInstall() {
+ if (imageUtil == null) {
+ imageUtil = new BitmapUtil();
+ }
+ return imageUtil;
+ }
+
+// @SuppressLint("NewApi")
+// public int getBitmapSize(Bitmap bitmap) {
+// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {// API
+// // 12
+// return bitmap.getByteCount();
+// }
+// return bitmap.getRowBytes() * bitmap.getHeight(); // earlier version
+// }
+
+ public String bitmaptoString(Drawable bitmap) {
+
+ BitmapDrawable drawable = (BitmapDrawable) bitmap;
+
+ return bitmaptoString(drawable.getBitmap());
+ }
+
+ public String bitmaptoString(Bitmap bitmap) {
+
+ // 将Bitmap转换成字符串
+
+ String string = null;
+
+ ByteArrayOutputStream bStream = new ByteArrayOutputStream();
+
+ bitmap.compress(CompressFormat.JPEG, 30, bStream);
+
+ byte[] bytes = bStream.toByteArray();
+
+ string = Base64.encodeToString(bytes, Base64.DEFAULT);
+
+ return string;
+
+ }
+
+ /**
+ * 读取图片属性:旋转的角度
+ *
+ * @param path
+ * 图片绝对路径
+ * @return degree旋转的角度
+ */
+ public static int readPictureDegree(String path) {
+ int degree = 0;
+ try {
+ ExifInterface exifInterface = new ExifInterface(path);
+ int orientation = exifInterface.getAttributeInt(
+ ExifInterface.TAG_ORIENTATION,
+ ExifInterface.ORIENTATION_NORMAL);
+ switch (orientation) {
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ degree = 90;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ degree = 180;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ degree = 270;
+ break;
+ }
+ } catch (IOException e) {
+ if (Log.LOG)
+ e.printStackTrace();
+ }
+ return degree;
+ }
+
+ /*
+ * 旋转图片
+ *
+ * @param angle
+ *
+ * @param bitmap
+ *
+ * @return Bitmap
+ */
+ public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
+ // 旋转图片 动作
+ Matrix matrix = new Matrix();
+ ;
+ matrix.postRotate(angle);
+ Log.e("PhotoGraphActivity", "旋转图片=" + angle);
+ // 创建新的图片
+ Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+ return resizedBitmap;
+ }
+ /**
+ * 图片资源的回收
+ * @param imageView
+ */
+ public static void releaseImageViewResouce(ImageView imageView) {
+ if (imageView == null) return;
+ Drawable drawable = imageView.getDrawable();
+ if (drawable != null && drawable instanceof BitmapDrawable) {
+ BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
+ Bitmap bitmap = bitmapDrawable.getBitmap();
+ if (bitmap != null && !bitmap.isRecycled()) {
+ bitmap.recycle();
+ }
+ }
+ }
+ /**
+ * 按规定长宽缩小图片
+ * @param in
+ * @param in2
+ * @param reqWidth
+ * @param reqHeight
+ * @return
+ */
+ public static synchronized Bitmap decodeSampledBitmapFromStream(InputStream in, InputStream in2,int reqWidth, int reqHeight) {
+
+ // First decode with inJustDecodeBounds=true to check dimensions
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(in, null, options);
+
+ BitmapFactory.Options options2 = new BitmapFactory.Options();
+ // Calculate inSampleSize
+ options2.inSampleSize = calculateInSampleSize(options, reqWidth,reqHeight);
+
+ // Decode bitmap with inSampleSize set
+ options2.inJustDecodeBounds = false;
+
+ return BitmapFactory.decodeStream(in2,null,options2);
+ }
+
+ public static int calculateInSampleSize(BitmapFactory.Options options,
+ int reqWidth, int reqHeight) {
+ // Raw height and width of image
+ final int height = options.outHeight;
+ final int width = options.outWidth;
+ int inSampleSize = 1;
+
+ //先根据宽度进行缩小
+ while (width / inSampleSize > reqWidth) {
+ inSampleSize++;
+ }
+ //然后根据高度进行缩小
+ while (height / inSampleSize > reqHeight) {
+ inSampleSize++;
+ }
+ return inSampleSize;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/img/ImageFileCache.java b/base/src/main/java/com/wlj/base/util/img/ImageFileCache.java
new file mode 100755
index 0000000..b84c8c1
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/img/ImageFileCache.java
@@ -0,0 +1,403 @@
+package com.wlj.base.util.img;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.DecimalFormat;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import com.wlj.base.util.AppConfig;
+import com.wlj.base.util.Log;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Environment;
+import android.os.StatFs;
+
+public class ImageFileCache {
+
+ private static final String CACHDIR = "imgCach";
+
+ private static final String WHOLESALE_CONV = ".cach";
+
+ /** 过期时间3天 **/
+
+ private static final long mTimeDiff = 3 * 24 * 60 * 60 * 1000;
+
+ public ImageFileCache()
+ {
+ // 清理文件缓存
+ removeCache(getDirectory());
+ }
+ /**
+ *
+ * @param url
+ * @return
+ */
+ public String getPath(String url){
+
+ String path = getDirectory() + "/" + convertUrlToFileName(url);
+ return path;
+ };
+
+ public Bitmap getImage(final String url) {
+
+ final String path = getDirectory() + "/" + convertUrlToFileName(url);
+
+ File file = new File(path);
+
+ if (file.exists()) {
+
+ Bitmap bmp = BitmapFactory.decodeFile(path);
+
+ if (bmp == null){
+
+ file.delete();
+ } else {
+
+ updateFileTime(path);
+
+ return bmp;
+ }
+
+ }
+
+ return null;
+
+ }
+
+ /*** 缓存空间大小 ****/
+
+ private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;
+
+ public void saveBmpToSd(Bitmap bm, String url) {
+
+ if (bm == null) {
+
+ // 需要保存的是一个空值
+
+ return;
+
+ }
+
+ // 判断sdcard上的空间
+
+ if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
+
+ // SD空间不足
+
+ return;
+
+ }
+
+ String filename = convertUrlToFileName(url);
+
+ String dir = getDirectory();
+ File filedir = new File(dir);
+
+ if (!filedir.exists()) {
+ filedir.mkdirs();
+ }
+
+ File file = new File(dir + "/" + filename);
+
+ try {
+
+ file.createNewFile();
+
+ OutputStream outStream = new FileOutputStream(file);
+
+ bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
+
+ outStream.flush();
+
+ outStream.close();
+
+ } catch (FileNotFoundException e) {
+
+ Log.w("ImageFileCache", "FileNotFoundException");
+
+ } catch (IOException e) {
+
+ Log.w("ImageFileCache", "IOException");
+
+ }
+
+ }
+
+ private static final int CACHE_SIZE = 10;
+
+ // 清理缓存
+
+ /**
+ *
+ * 计算存储目录下的文件大小,
+ *
+ * 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
+ *
+ * 那么删除40%最近没有被使用的文件
+ *
+ * @param dirPath
+ *
+ *
+ */
+
+ private boolean removeCache(String dirPath) {
+
+ File dir = new File(dirPath);
+
+ File[] files = dir.listFiles();
+
+ if (files == null) {
+
+ return true;
+
+ }
+
+ if (!Environment.getExternalStorageState().equals(
+
+ Environment.MEDIA_MOUNTED)) {
+
+ return false;
+
+ }
+
+ int dirSize = 0;
+
+ for (int i = 0; i < files.length; i++) {
+
+ if (files[i].getName().contains(WHOLESALE_CONV)) {
+
+ dirSize += files[i].length();
+
+ }
+
+ }
+
+ if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
+
+ int removeFactor = (int) ((0.4 * files.length) + 1);
+
+ Arrays.sort(files, new FileLastModifSort());
+
+ Log.i("ImageFileCache", "清理缓存文件");
+
+ for (int i = 0; i < removeFactor; i++) {
+
+ if (files[i].getName().contains(WHOLESALE_CONV)) {
+
+ files[i].delete();
+
+ }
+
+ }
+
+ }
+
+ if (freeSpaceOnSd() <= CACHE_SIZE) {
+
+ return false;
+
+ }
+
+ return true;
+ }
+ public String removeAllCache(){
+ File file = new File(getDirectory());
+ File[] files = file.listFiles();
+ if(files == null || files.length < 1){
+ return "不需要清理";
+ }
+
+ long dirSize = 0;
+
+ for (int i = 0; i < files.length; i++) {
+ dirSize += files[i].length();
+ boolean isdel = files[i].delete();
+ Log.e("ImageFileCache", isdel+"");
+ }
+ DecimalFormat df = new DecimalFormat("0.000");
+ return "成功清理"+df.format(dirSize/1048576.00)+"M";
+ }
+
+ public String getCacheSise(){
+
+ File file = new File(getDirectory());
+ File[] files = file.listFiles();
+ long dirSize = 0;
+ if(files == null )
+ return 0+"M";
+ for (int i = 0; i < files.length; i++) {
+ dirSize += files[i].length();
+ }
+ DecimalFormat df = new DecimalFormat("0.000");
+ return df.format(dirSize/1048576.00)+"M";
+
+ }
+
+ public boolean removeBitmap(String name) {
+ if (name != null && !"".equals(name)) {
+ String path = getPath(name);
+ File file = new File(path);
+ if (file.exists()) {
+ file.delete();
+
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ *
+ * 根据文件的最后修改时间进行排序*
+ */
+ private class FileLastModifSort implements Comparator {
+
+ public int compare(File arg0, File arg1) {
+
+ if (arg0.lastModified() > arg1.lastModified()) {
+
+ return 1;
+
+ } else if (arg0.lastModified() == arg1.lastModified()) {
+
+ return 0;
+
+ } else {
+
+ return -1;
+
+ }
+
+ }
+
+ }
+
+ /**
+ *
+ * 删除过期文件
+ *
+ * @param dirPath
+ *
+ * @param filename
+ */
+
+ public void removeExpiredCache(String dirPath, String filename) {
+
+ File file = new File(dirPath, filename);
+
+ if (System.currentTimeMillis() - file.lastModified() > mTimeDiff) {
+
+ Log.i("ImageFileCache", "Clear some expiredcache files ");
+
+ file.delete();
+
+ }
+
+ }
+
+ /**
+ *
+ * 修改文件的最后修改时间
+ *
+ * 这里需要考虑,是否将使用的图片日期改为当前日期
+ *
+ * @param path
+ */
+
+ public void updateFileTime(String path) {
+
+ File file = new File(path);
+
+ long newModifiedTime = System.currentTimeMillis();
+
+ file.setLastModified(newModifiedTime);
+
+ }
+
+ /**
+ *
+ * 计算sdcard上的剩余空间
+ *
+ * @return
+ */
+
+ private int MB = 1024 * 1024;
+
+ private int freeSpaceOnSd() {
+
+ StatFs stat = new StatFs(Environment.getExternalStorageDirectory()
+ .getPath());
+
+ double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat
+ .getBlockSize()) / MB;
+
+ return (int) sdFreeMB;
+
+ }
+
+ /** 将url转成文件名 **/
+
+ private String convertUrlToFileName(String url) {
+
+ String[] strs = url.split("/");
+
+ return strs[strs.length - 1] + WHOLESALE_CONV;
+
+ }
+
+ /** 获得缓存目录 **/
+
+ private String getDirectory() {
+
+ String dir = AppConfig.getAppConfig().getImagePath() + CACHDIR;
+
+ String substr = dir.substring(0, 4);
+
+ if (substr.equals("/mnt")) {
+
+ dir = dir.replace("/mnt", "");
+
+ }
+
+ return dir;
+
+ }
+
+ /**** 取SD卡路径不带/ ****/
+ public static String getSDPath() {
+
+ File sdDir = null;
+
+ boolean sdCardExist = Environment.getExternalStorageState().equals(
+
+ Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
+
+ if (sdCardExist) {
+
+ sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
+
+ }
+
+ if (sdDir != null)
+
+ {
+
+ return sdDir.toString();
+
+ } else
+
+ {
+
+ return "";
+
+ }
+
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/util/img/ImageGetForHttp.java b/base/src/main/java/com/wlj/base/util/img/ImageGetForHttp.java
new file mode 100755
index 0000000..fa262ac
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/img/ImageGetForHttp.java
@@ -0,0 +1,43 @@
+package com.wlj.base.util.img;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import com.wlj.base.web.HttpPost;
+
+
+public class ImageGetForHttp {
+
+ private static final String LOG_TAG = "ImageGetForHttp";
+
+ public static Bitmap downloadBitmap(String url) {
+
+ try {
+ HttpPost httpPost = new HttpPost(new URL(url));
+ InputStream inputStream = httpPost.getInputStream();
+
+
+ BitmapFactory.Options opt = new BitmapFactory.Options();
+
+ opt.inPreferredConfig = Bitmap.Config.RGB_565;
+
+ opt.inPurgeable = true;
+
+ opt.inInputShareable = true;
+
+ Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, opt);
+
+ return bitmap;
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/img/ImageLrucache.java b/base/src/main/java/com/wlj/base/util/img/ImageLrucache.java
new file mode 100755
index 0000000..b58451d
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/img/ImageLrucache.java
@@ -0,0 +1,89 @@
+package com.wlj.base.util.img;
+
+import com.wlj.base.util.GetResourceImage;
+import com.wlj.base.util.Log;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.support.v4.util.LruCache;
+
+/**
+ * Lrucache 图片缓存
+ * @author wlj
+ *
+ */
+public class ImageLrucache {
+
+ private LruCache lrucache;
+ private static ImageLrucache mImageLrucache;
+
+ public ImageLrucache(){
+ //获取系统分配给每个应用程序的最大内存,每个应用系统分配32M
+ long maxMemory = Runtime.getRuntime().maxMemory();
+
+ //给LruCache分配1/4 8M
+ int cacheSize = (int) (maxMemory/4);
+
+ lrucache = new LruCache(cacheSize){
+
+ //必须重写此方法,来测量Bitmap的大小
+ @Override
+ protected int sizeOf(String key, Bitmap value) {
+ int size = value.getRowBytes()* value.getHeight();
+ return size;
+ }
+
+ };
+ }
+
+ public static ImageLrucache getInstance(){
+ if(mImageLrucache == null){
+ mImageLrucache = new ImageLrucache();
+ }
+ return mImageLrucache;
+ }
+
+ /**
+ * 添加Bitmap到内存缓存
+ * @param key
+ * @param bitmap
+ */
+ public void addBitmapToMemoryCache(String key,Bitmap bitmap){
+ if (getBitmapFromMemCache(key) == null && bitmap != null) {
+ lrucache.put(key, bitmap);
+ Log.i("ImageLrucache", lrucache.size()+" "+lrucache.createCount());
+ }
+ }
+
+ /**
+ * 从内存缓存中获取一个Bitmap
+ * @param key
+ * @return
+ */
+ public Bitmap getBitmapFromMemCache(String key) {
+
+ return lrucache.get(key);
+ }
+
+ /**
+ * 获取 资源文件 图片
+ */
+ public Bitmap getResourceBitmap(int resId, Context context) {
+
+ Bitmap bitmapImage = null;
+ bitmapImage = getBitmapFromMemCache(resId+"");
+
+ if (bitmapImage == null) {
+ bitmapImage = GetResourceImage.get(context, resId);
+ this.addBitmapToMemoryCache(resId+"",bitmapImage);
+ }
+ return bitmapImage;
+ }
+
+ public void clearCache(){
+ lrucache.evictAll();
+ System.gc();
+ System.runFinalization();
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/util/img/LazyScrollView.java b/base/src/main/java/com/wlj/base/util/img/LazyScrollView.java
new file mode 100755
index 0000000..c6f7e22
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/img/LazyScrollView.java
@@ -0,0 +1,119 @@
+package com.wlj.base.util.img;
+//来自:http://blog.csdn.net/listening_music/article/details/7192629
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ListView;
+
+/**
+ * ScrollView的Touch事件,监听移动的位置。然后来实现移动底部加载更多
+ * @author wlj
+ *
+ */
+public class LazyScrollView extends ListView{
+ private static final String tag="LazyScrollView";
+ private Handler handler;
+ private View view;
+ public LazyScrollView(Context context) {
+ super(context);
+ }
+ public LazyScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ public LazyScrollView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+ //这个获得总的高度
+ public int computeVerticalScrollRange(){
+ return super.computeHorizontalScrollRange();
+ }
+ public int computeVerticalScrollOffset(){
+ return super.computeVerticalScrollOffset();
+ }
+ private void init(){
+
+ this.setOnTouchListener(onTouchListener);
+ handler=new Handler(){
+ @Override
+ public void handleMessage(Message msg) {
+ // process incoming messages here
+ super.handleMessage(msg);
+ switch(msg.what){
+ case 1:
+ //getScrollY(): scrolled top position of this view
+ //getScrollY() + getHeight() 当前最底部的y
+ // view.getMeasuredHeight(): 全部高度,包括隐藏
+ if(view.getMeasuredHeight() <= getScrollY() + getHeight()) {
+ if(onScrollListener!=null){
+ onScrollListener.onBottom();
+ }
+
+ }else if(getScrollY()==0){
+ if(onScrollListener!=null){
+ onScrollListener.onTop();
+ }
+ }
+ else{
+ if(onScrollListener!=null){
+ onScrollListener.onScroll();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ }
+
+ OnTouchListener onTouchListener=new OnTouchListener(){
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ break;
+ case MotionEvent.ACTION_UP:
+ if(view!=null&&onScrollListener!=null){
+ handler.sendMessageDelayed(handler.obtainMessage(1), 200);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return false;
+ }
+
+ };
+
+ /**
+ * 获得参考的View,主要是为了获得它的MeasuredHeight,然后和滚动条的ScrollY+getHeight作比较。
+ */
+ public void getView(){
+ this.view=getChildAt(0);
+ if(view!=null){
+ init();
+ }
+ }
+
+ /**
+ * 定义接口
+ * @author admin
+ *
+ */
+ public interface OnScrollListener{
+ void onBottom();
+ void onTop();
+ void onScroll();
+ }
+
+ private OnScrollListener onScrollListener;
+ public void setOnScrollListener(OnScrollListener onScrollListener){
+ this.onScrollListener=onScrollListener;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/util/img/LoadImage.java b/base/src/main/java/com/wlj/base/util/img/LoadImage.java
new file mode 100755
index 0000000..f706186
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/img/LoadImage.java
@@ -0,0 +1,265 @@
+package com.wlj.base.util.img;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import com.wlj.base.util.ExecutorServices;
+
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.Message;
+import android.view.View;
+import android.widget.ImageView;
+
+public class LoadImage {
+
+ private ExecutorService executorService; // 固定五个线程来
+
+// private ImageMemoryCache memoryCache;// 内存缓存
+// private BitmapCache bitmapCache;
+ private ImageLrucache imageLrucache;
+
+ private ImageFileCache fileCache;// 文件缓存
+
+ private Map taskMap;// 存放任务
+
+ private static LoadImage loadImage;
+
+ /**
+ * 在getview时先addtask 当滚动停止的时候调用doTask
+ */
+ private LoadImage() {
+
+ executorService = ExecutorServices.getExecutorService();
+
+// memoryCache = new ImageMemoryCache();
+// bitmapCache = BitmapCache.getInstance();
+ imageLrucache = ImageLrucache.getInstance();
+
+ fileCache = new ImageFileCache();
+
+ taskMap = new HashMap();
+ futureList = new ArrayList();
+ }
+
+ public static LoadImage getinstall() {
+
+ if(loadImage == null){
+ loadImage = new LoadImage();
+ }
+ return loadImage;
+ }
+
+ /**
+ *
+ * @param url
+ * @param img
+ * imageview的tag是需要下载的url
+ */
+ public void addTask(String url, ImageView img) {
+ futureList.clear();
+ loadcomplete = null;
+ if (url == null)
+ return;
+ img.setTag(url);
+ Bitmap bitmap = imageLrucache.getBitmapFromMemCache(url);
+
+ if (bitmap != null && img != null)
+ {
+ img.setImageBitmap(bitmap);
+ img.setVisibility(View.VISIBLE);
+ } else {
+ synchronized (taskMap) {
+ taskMap.put(Integer.toString(img.hashCode()), img);
+ }
+
+ }
+
+ }
+
+ private LoadComplete loadcomplete;
+ private int taskSize;
+ private List futureList;
+
+ /**
+ * 统计用的
+ * @param url
+ * @param img
+ * @param loadcomplete
+ */
+ public void addTask(String url, ImageView img,LoadComplete loadcomplete) {
+ this.loadcomplete = loadcomplete;
+ futureList.clear();
+ if (url == null)
+ return;
+ img.setTag(url);
+ synchronized (taskMap) {
+ taskMap.put(Integer.toString(img.hashCode()), img);
+ }
+
+ }
+ /**
+ * 如果是调用的含统计功能的addTask,需要把所有要统计的task加入(addTask)完,
+ * 最后再doTask,这样才能正确统计任务完成
+ */
+ public void doTask() {
+ taskSize = taskMap.size();
+ synchronized (taskMap) {
+
+ Collection con = taskMap.values();
+
+ for (ImageView i : con) {
+
+ if (i != null) {
+
+ if (i.getTag() != null) {
+
+ loadImage((String) i.getTag(), i);
+
+ }
+
+ }
+
+ }
+ taskMap.clear();
+ }
+
+ }
+
+ private void loadImage(String url, ImageView img) {
+
+ /*** 加入新的任务 ***/
+
+ Future submit = executorService.submit(new TaskWithResult(new TaskHandler(url, img),url));
+
+ }
+
+ /*** 获得一个图片,从三个地方获取,首先是内存缓存,然后是文件缓存,最后从网络获取 ***/
+
+ private Bitmap getBitmap(String url) {
+
+ // 从内存缓存中获取图片
+ Bitmap result;
+
+ result = imageLrucache.getBitmapFromMemCache(url);
+
+ if (result == null) {
+
+ // 文件缓存中获取
+ result = fileCache.getImage(url);
+
+ if (result == null) {
+
+ // 从网络获取
+ result = ImageGetForHttp.downloadBitmap(url);
+
+ if (result != null) {
+
+ imageLrucache.addBitmapToMemoryCache(url, result);
+
+ fileCache.saveBmpToSd(result, url);
+// result = fileCache.getImage(url);
+ }
+
+ } else {
+ // 添加到内存缓存
+ imageLrucache.addBitmapToMemoryCache(url,result);
+ }
+
+ }
+
+ return result;
+
+ }
+
+ /*** 完成消息 ***/
+
+ private class TaskHandler extends Handler {
+
+ String url = "";
+
+ ImageView img;
+
+ public TaskHandler(String url, ImageView img) {
+
+ this.url = url;
+
+ this.img = img;
+
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+
+ /*** 查看imageview需要显示的图片是否被改变 ***/
+
+ if (img != null && url.equals(img.getTag())) {
+
+ if (msg.obj != null && img != null) {
+
+ Bitmap bitmap = (Bitmap) msg.obj;
+
+ img.setImageBitmap(bitmap);
+ img.setVisibility(View.VISIBLE);
+// bitmap.recycle();
+ futureList.add("");
+ if(loadcomplete!= null && futureList.size() == taskSize){
+ loadcomplete.onComplete();
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ /*** 子线程任务 ***/
+
+ private class TaskWithResult implements Callable {
+
+ private String url;
+
+ private Handler handler;
+
+ public TaskWithResult(Handler handler, String url) {
+
+ this.url = url;
+
+ this.handler = handler;
+
+ }
+
+ @Override
+ public String call() throws Exception {
+
+ Message msg = new Message();
+
+ msg.obj = getBitmap(url);
+
+ if (msg.obj != null) {
+
+ handler.sendMessage(msg);
+
+ }
+
+ return url;
+
+ }
+
+ }
+
+ public interface LoadComplete{
+
+ void onComplete();
+
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/util/statusbar/StatusBarUtil.java b/base/src/main/java/com/wlj/base/util/statusbar/StatusBarUtil.java
new file mode 100644
index 0000000..a6c6e26
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/statusbar/StatusBarUtil.java
@@ -0,0 +1,598 @@
+package com.wlj.base.util.statusbar;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Build;
+import android.support.annotation.ColorInt;
+import android.support.v4.widget.DrawerLayout;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.LinearLayout;
+
+/**
+ * Created by Jaeger on 16/2/14.
+ *
+ * Email: chjie.jaeger@gmail.com
+ * GitHub: https://github.com/laobie
+ */
+public class StatusBarUtil {
+
+ public static final int DEFAULT_STATUS_BAR_ALPHA = 112;
+
+ /**
+ * 设置状态栏颜色
+ *
+ * @param activity 需要设置的 activity
+ * @param color 状态栏颜色值
+ */
+ public static void setColor(Activity activity, @ColorInt int color) {
+ setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA);
+ }
+
+ /**
+ * 设置状态栏颜色
+ *
+ * @param activity 需要设置的activity
+ * @param color 状态栏颜色值
+ * @param statusBarAlpha 状态栏透明度
+ */
+
+ public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
+ int count = decorView.getChildCount();
+ if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
+ decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
+ } else {
+ StatusBarView statusView = createColorStatusBarView(activity, color, statusBarAlpha);
+ decorView.addView(statusView);
+ }
+ setFitsSystemWindowsAndClip(activity,true);
+ }
+ }
+
+ /**
+ * 为滑动返回界面设置状态栏颜色
+ *
+ * @param activity 需要设置的activity
+ * @param color 状态栏颜色值
+ */
+ public static void setColorForSwipeBack(Activity activity, int color) {
+ setColorForSwipeBack(activity, color, DEFAULT_STATUS_BAR_ALPHA);
+ }
+
+ /**
+ * 为滑动返回界面设置状态栏颜色
+ *
+ * @param activity 需要设置的activity
+ * @param color 状态栏颜色值
+ * @param statusBarAlpha 状态栏透明度
+ */
+ public static void setColorForSwipeBack(Activity activity, @ColorInt int color, int statusBarAlpha) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ ViewGroup contentView = ((ViewGroup) activity.findViewById(android.R.id.content));
+ contentView.setPadding(0, getStatusBarHeight(activity), 0, 0);
+ contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
+ setTransparentForWindowFLAG(activity);
+ }
+ }
+
+ /**
+ * 设置状态栏纯色 不加半透明效果
+ *
+ * @param activity 需要设置的 activity
+ * @param color 状态栏颜色值
+ */
+ public static void setColorNoTranslucent(Activity activity, @ColorInt int color) {
+ setColor(activity, color, 0);
+ }
+
+ /**
+ * 设置状态栏颜色(5.0以下无半透明效果,不建议使用)
+ *
+ * @param activity 需要设置的 activity
+ * @param color 状态栏颜色值
+ */
+ @Deprecated
+ public static void setColorDiff(Activity activity, @ColorInt int color) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+ transparentFlags(activity);
+ ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
+ // 移除半透明矩形,以免叠加
+ if (contentView.getChildCount() > 1) {
+ contentView.getChildAt(1).setBackgroundColor(color);
+ } else {
+ contentView.addView(createColorStatusBarView(activity, color));
+ }
+ setFitsSystemWindowsAndClip(activity,true);
+ }
+
+ /**
+ * 使状态栏半透明
+ *
+ * 适用于图片作为背景的界面,此时需要图片填充到状态栏
+ *
+ * @param activity 需要设置的activity
+ */
+ public static void setTranslucent(Activity activity) {
+ setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA);
+ }
+
+ /**
+ * 使状态栏半透明
+ *
+ * 适用于图片作为背景的界面,此时需要图片填充到状态栏
+ *
+ * @param activity 需要设置的activity
+ * @param statusBarAlpha 状态栏透明度
+ */
+ public static void setTranslucent(Activity activity, int statusBarAlpha) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+ FlagsAndsetFitsSystemWindows(activity);
+ addTranslucentView(activity, statusBarAlpha);
+ }
+
+ /**
+ * 针对根布局是 CoordinatorLayout, 使状态栏半透明
+ *
+ * 适用于图片作为背景的界面,此时需要图片填充到状态栏
+ *
+ * @param activity 需要设置的activity
+ * @param statusBarAlpha 状态栏透明度
+ */
+ public static void setTranslucentForCoordinatorLayout(Activity activity, int statusBarAlpha) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+ transparentFlags(activity);
+ addTranslucentView(activity, statusBarAlpha);
+ }
+
+ /**
+ * 添加 flags和 setFitsSystemWindows
+ *
+ * @param activity 需要设置的activity
+ */
+ public static void FlagsAndsetFitsSystemWindows(Activity activity) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+ transparentFlags(activity);
+ setFitsSystemWindowsAndClip(activity,true);
+ }
+
+ /**
+ * 使状态栏透明(5.0以上半透明效果,不建议使用)
+ *
+ * 适用于图片作为背景的界面,此时需要图片填充到状态栏
+ *
+ * @param activity 需要设置的activity
+ */
+ @Deprecated
+ public static void setTranslucentDiff(Activity activity) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ // 设置状态栏透明
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ setFitsSystemWindowsAndClip(activity,true);
+ }
+ }
+
+ /**
+ * 为DrawerLayout 布局设置状态栏变色
+ *
+ * @param activity 需要设置的activity
+ * @param drawerLayout DrawerLayout
+ * @param color 状态栏颜色值
+ */
+ public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
+ setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA);
+ }
+
+ /**
+ * 为DrawerLayout 布局设置状态栏颜色,纯色
+ *
+ * @param activity 需要设置的activity
+ * @param drawerLayout DrawerLayout
+ * @param color 状态栏颜色值
+ */
+ public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
+ setColorForDrawerLayout(activity, drawerLayout, color, 0);
+ }
+
+ /**
+ * 为DrawerLayout 布局设置状态栏变色
+ *
+ * @param activity 需要设置的activity
+ * @param drawerLayout DrawerLayout
+ * @param color 状态栏颜色值
+ * @param statusBarAlpha 状态栏透明度
+ */
+ public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color,
+ int statusBarAlpha) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
+ } else {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ }
+ // 生成一个状态栏大小的矩形
+ // 添加 statusBarView 到布局中
+ ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
+ if (contentLayout.getChildCount() > 0 && contentLayout.getChildAt(0) instanceof StatusBarView) {
+ contentLayout.getChildAt(0).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
+ } else {
+ StatusBarView statusBarView = createColorStatusBarView(activity, color);
+ contentLayout.addView(statusBarView, 0);
+ }
+ // 内容布局不是 LinearLayout 时,设置padding top
+ if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
+ contentLayout.getChildAt(1)
+ .setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(),
+ contentLayout.getPaddingRight(), contentLayout.getPaddingBottom());
+ }
+ // 设置属性
+ ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
+ drawerLayout.setFitsSystemWindows(false);
+ contentLayout.setFitsSystemWindows(false);
+ contentLayout.setClipToPadding(true);
+ drawer.setFitsSystemWindows(false);
+
+ addTranslucentView(activity, statusBarAlpha);
+ }
+
+ /**
+ * 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用)
+ *
+ * @param activity 需要设置的activity
+ * @param drawerLayout DrawerLayout
+ * @param color 状态栏颜色值
+ */
+ @Deprecated
+ public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ // 生成一个状态栏大小的矩形
+ ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
+ if (contentLayout.getChildCount() > 0 && contentLayout.getChildAt(0) instanceof StatusBarView) {
+ contentLayout.getChildAt(0).setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA));
+ } else {
+ // 添加 statusBarView 到布局中
+ StatusBarView statusBarView = createColorStatusBarView(activity, color);
+ contentLayout.addView(statusBarView, 0);
+ }
+ // 内容布局不是 LinearLayout 时,设置padding top
+ if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
+ contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
+ }
+ // 设置属性
+ ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
+ drawerLayout.setFitsSystemWindows(false);
+ contentLayout.setFitsSystemWindows(false);
+ contentLayout.setClipToPadding(true);
+ drawer.setFitsSystemWindows(false);
+ }
+ }
+
+ /**
+ * 为 DrawerLayout 布局设置状态栏透明
+ *
+ * @param activity 需要设置的activity
+ * @param drawerLayout DrawerLayout
+ */
+ public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
+ setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA);
+ }
+
+ /**
+ * 为 DrawerLayout 布局设置状态栏透明
+ *
+ * @param activity 需要设置的activity
+ * @param drawerLayout DrawerLayout
+ */
+ public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int statusBarAlpha) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+ setTransparentForDrawerLayout(activity, drawerLayout);
+ addTranslucentView(activity, statusBarAlpha);
+ }
+
+ /**
+ * 为 DrawerLayout 布局设置状态栏透明
+ *
+ * @param activity 需要设置的activity
+ * @param drawerLayout DrawerLayout
+ */
+ public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
+ } else {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ }
+
+ ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
+ // 内容布局不是 LinearLayout 时,设置padding top
+ if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
+ contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
+ }
+
+ // 设置属性
+ ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
+ drawerLayout.setFitsSystemWindows(false);
+ contentLayout.setFitsSystemWindows(false);
+ contentLayout.setClipToPadding(true);
+ drawer.setFitsSystemWindows(false);
+ }
+
+ /**
+ * 为 DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用)
+ *
+ * @param activity 需要设置的activity
+ * @param drawerLayout DrawerLayout
+ */
+ @Deprecated
+ public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ // 设置状态栏透明
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ // 设置内容布局属性
+ ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
+ contentLayout.setFitsSystemWindows(true);
+ contentLayout.setClipToPadding(true);
+ // 设置抽屉布局属性
+ ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1);
+ vg.setFitsSystemWindows(false);
+ // 设置 DrawerLayout 属性
+ drawerLayout.setFitsSystemWindows(false);
+ }
+ }
+
+ /**
+ * 为头部是 ImageView 的界面设置状态栏全透明
+ *
+ * @param activity 需要设置的activity
+ * @param needOffsetView 需要向下偏移的 View
+ */
+ public static void setTransparentForImageView(Activity activity, View needOffsetView) {
+ setTranslucentForImageView(activity, 0, needOffsetView);
+ }
+
+ /**
+ * 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度)
+ *
+ * @param activity 需要设置的activity
+ * @param needOffsetView 需要向下偏移的 View
+ */
+ public static void setTranslucentForImageView(Activity activity, View needOffsetView) {
+ setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
+ }
+
+ /**
+ * 为头部是 ImageView 的界面设置状态栏透明
+ *
+ * @param activity 需要设置的activity
+ * @param statusBarAlpha 状态栏透明度
+ * @param needOffsetView 需要向下偏移的 View
+ */
+ public static void setTranslucentForImageView(Activity activity, int statusBarAlpha, View needOffsetView) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+ setFitsSystemWindowsAndClip(activity,false);
+ setTransparentForWindowFLAG(activity);
+
+// addTranslucentView(activity, statusBarAlpha);
+ if (needOffsetView != null) {
+ ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();
+ layoutParams.setMargins(0, getStatusBarHeight(activity), 0, 0);
+ }
+ }
+
+ /**
+ * 为 fragment 头部是 ImageView 的设置状态栏透明
+ *
+ * @param activity fragment 对应的 activity
+ * @param needOffsetView 需要向下偏移的 View
+ */
+ public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) {
+ setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
+ }
+
+ /**
+ * 为 fragment 头部是 ImageView 的设置状态栏透明
+ *
+ * @param activity fragment 对应的 activity
+ * @param needOffsetView 需要向下偏移的 View
+ */
+ public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) {
+ setTranslucentForImageViewInFragment(activity, 0, needOffsetView);
+ }
+
+ /**
+ * 为 fragment 头部是 ImageView 的设置状态栏透明
+ *
+ * @param activity fragment 对应的 activity
+ * @param statusBarAlpha 状态栏透明度
+ * @param needOffsetView 需要向下偏移的 View
+ */
+ public static void setTranslucentForImageViewInFragment(Activity activity, int statusBarAlpha, View needOffsetView) {
+ setTranslucentForImageView(activity, statusBarAlpha, needOffsetView);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ) {
+ clearPreviousSetting(activity);
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * 移除添加的 StatusBarView块和添加的padding
+ * @param activity
+ */
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ private static void clearPreviousSetting(Activity activity) {
+ ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
+ int count = decorView.getChildCount();
+ if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
+ decorView.removeViewAt(count - 1);
+ ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
+ rootView.setPadding(0, 0, 0, 0);
+ }
+ }
+
+ /**
+ * 添加半透明矩形条
+ *
+ * @param activity 需要设置的 activity
+ * @param statusBarAlpha 透明值
+ */
+ private static void addTranslucentView(Activity activity, int statusBarAlpha) {
+ ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
+ if (contentView.getChildCount() > 1) {
+ contentView.getChildAt(1).setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));
+ } else {
+ contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha));
+ }
+ }
+
+ /**
+ * 生成一个和状态栏大小相同的彩色矩形条
+ *
+ * @param activity 需要设置的 activity
+ * @param color 状态栏颜色值
+ * @return 状态栏矩形条
+ */
+ private static StatusBarView createColorStatusBarView(Activity activity, @ColorInt int color) {
+ // 绘制一个和状态栏一样高的矩形
+ StatusBarView statusBarView = new StatusBarView(activity);
+ LinearLayout.LayoutParams params =
+ new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
+ statusBarView.setLayoutParams(params);
+ statusBarView.setBackgroundColor(color);
+ return statusBarView;
+ }
+
+ /**
+ * 生成一个和状态栏大小相同的半透明矩形条
+ *
+ * @param activity 需要设置的activity
+ * @param color 状态栏颜色值
+ * @param alpha 透明值
+ * @return 状态栏矩形条
+ */
+ private static StatusBarView createColorStatusBarView(Activity activity, @ColorInt int color, int alpha) {
+ // 绘制一个和状态栏一样高的矩形
+ StatusBarView statusBarView = new StatusBarView(activity);
+ LinearLayout.LayoutParams params =
+ new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
+ statusBarView.setLayoutParams(params);
+ statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
+ return statusBarView;
+ }
+
+ /**
+ *
+ * rootView.setFitsSystemWindows(true);
+ rootView.setClipToPadding(true);
+ * 设置根布局参数
+ */
+ private static void setFitsSystemWindowsAndClip(Activity activity,boolean is) {
+ ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
+ rootView.setFitsSystemWindows(is);
+ rootView.setClipToPadding(is);
+ }
+
+ /**
+ * 设置透明
+ */
+ public static void setTransparentForWindowFLAG(Activity activity) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
+ activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ }
+ }
+
+ /**
+ * 透明 FLAG 的设置,
+ * FLAG_TRANSLUCENT_STATUS
+ */
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ public static void transparentFlags(Activity activity) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
+ } else {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ }
+ }
+
+ /**
+ * 创建 alpha 矩形 View
+ *
+ * @param alpha 透明值
+ * @return 半透明 View
+ */
+ private static StatusBarView createTranslucentStatusBarView(Activity activity, int alpha) {
+ // 绘制一个和状态栏一样高的矩形
+ StatusBarView statusBarView = new StatusBarView(activity);
+ LinearLayout.LayoutParams params =
+ new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
+ statusBarView.setLayoutParams(params);
+ statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
+ return statusBarView;
+ }
+
+ /**
+ * 获取状态栏高度
+ *
+ * @param context context
+ * @return 状态栏高度
+ */
+ private static int getStatusBarHeight(Context context) {
+ // 获得状态栏高度
+ int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
+ return context.getResources().getDimensionPixelSize(resourceId);
+ }
+
+ /**
+ * 计算状态栏颜色
+ *
+ * @param color color值
+ * @param alpha alpha值
+ * @return 最终的状态栏颜色
+ */
+ private static int calculateStatusColor(@ColorInt int color, int alpha) {
+ float a = 1 - alpha / 255f;
+ int red = color >> 16 & 0xff;
+ int green = color >> 8 & 0xff;
+ int blue = color & 0xff;
+ red = (int) (red * a + 0.5);
+ green = (int) (green * a + 0.5);
+ blue = (int) (blue * a + 0.5);
+ return 0xff << 24 | red << 16 | green << 8 | blue;
+ }
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/util/statusbar/StatusBarView.java b/base/src/main/java/com/wlj/base/util/statusbar/StatusBarView.java
new file mode 100644
index 0000000..bde402e
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/util/statusbar/StatusBarView.java
@@ -0,0 +1,21 @@
+package com.wlj.base.util.statusbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * Created by Jaeger on 16/6/8.
+ *
+ * Email: chjie.jaeger@gmail.com
+ * GitHub: https://github.com/laobie
+ */
+public class StatusBarView extends View {
+ public StatusBarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public StatusBarView(Context context) {
+ super(context);
+ }
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/web/BaseURL.java b/base/src/main/java/com/wlj/base/web/BaseURL.java
new file mode 100644
index 0000000..a2aefc0
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/BaseURL.java
@@ -0,0 +1,8 @@
+package com.wlj.base.web;
+
+public class BaseURL {
+
+// public static final String HOST = "http://192.168.0.6:8080/duohaowan/";
+ public static final String HOST = "http://121.40.177.251:3330/duohaowan/";
+
+}
diff --git a/base/src/main/java/com/wlj/base/web/BaseWebMain.java b/base/src/main/java/com/wlj/base/web/BaseWebMain.java
new file mode 100755
index 0000000..011e727
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/BaseWebMain.java
@@ -0,0 +1,131 @@
+package com.wlj.base.web;
+
+
+import java.net.ConnectException;
+import java.net.URL;
+
+import com.wlj.base.util.RequestException;
+
+import android.content.res.Resources.NotFoundException;
+
+ /*
+ *
+ * @author lymava
+ *
+ */
+public class BaseWebMain {
+ public static URL url = null;
+
+ public static void main(String[] args) throws Exception {
+ String urlString = "http://localhost:8080/chuang/face/userfront/getYuyueList.do";
+
+ String key = "e5d50a5bb7a7e23c5441ef29";
+ String name = "facema";
+ String json = "{}";
+
+ String request_data = request_data(urlString, key, name,json);
+
+ System.out.println(request_data);
+ }
+
+ public static final Integer client_type_xml = 1;
+ public static final Integer client_type_json = 2;
+
+ public static String request_data(String url,String key,String name,String json) throws Exception {
+
+ String randCode = System.currentTimeMillis()+"";
+
+ HttpPost hp = null;
+
+ String tempKey = Md5Util.MD5Normal(key+randCode);
+ try {
+
+ Boolean isEncryption = false;
+
+ hp = new HttpPost(new URL(url));
+ hp.addParemeter("name", name);
+ hp.addParemeter("randCode", randCode);
+ hp.addParemeter("encrpt", "enAes");
+ hp.addParemeter("isEncryption",isEncryption.toString());
+ hp.addParemeter("mode",client_type_json+"");
+
+ String reqxml = json;
+ String enStr = reqxml;
+ hp.addParemeter("data", enStr);
+ String mac = Md5Util.MD5Normal(tempKey+name+ enStr);
+ hp.addParemeter("mac", mac);
+
+ } catch (Exception e) {
+ //缴费或查询失败 如果是缴费 这个当缴费失败处理
+ e.printStackTrace();
+ }
+
+ String result = null;
+ try {
+ result = hp.getResult();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * 进行一次充值缴费
+ * @param args
+ * @throws Exception 3des 类初始话失败
+ */
+ public static void request_test(Encrpt td,URL url) throws Exception {
+
+ String key = "e5d50a5bb7a7e23c5441ef29";
+ String randCode = System.currentTimeMillis()+"";
+ String name = "facema";
+
+ HttpPost hp = null;
+
+ String tempKey = Md5Util.MD5Normal(key+randCode);
+
+
+ try {
+
+ Boolean isEncryption = false;
+
+ hp = new HttpPost(url);
+ hp.addParemeter("name", name);
+ hp.addParemeter("randCode", randCode);
+ hp.addParemeter("encrpt", "enAes");
+ hp.addParemeter("isEncryption",isEncryption.toString());
+ hp.addParemeter("mode",client_type_json+"");
+
+ String reqxml = "{}";
+ String enStr = reqxml;
+ if(isEncryption){
+ enStr = td.encrypt(reqxml,tempKey);
+ }
+ hp.addParemeter("data", enStr);
+ String mac = Md5Util.MD5Normal(tempKey+name+ enStr);
+ hp.addParemeter("mac", mac);
+
+ } catch (Exception e) {
+ //缴费或查询失败 如果是缴费 这个当缴费失败处理
+ e.printStackTrace();
+ }
+
+ String result;
+ try {
+ result = hp.getResult();
+
+ if(!result.contains("<") && !result.contains("{")){
+ result = td.decrypt(result, tempKey);
+ }
+
+ System.out.println(result);
+ } catch (ConnectException e) {
+ //链接未打开缴费或查询失败 如果是缴费 这个当缴费失败处理
+ e.printStackTrace();
+ } catch (Exception e){
+ //解密失败或者通讯失败 如果是缴费两种失败都把这次缴费挂起 处理
+ e.printStackTrace();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/web/CallWebserviceImp.java b/base/src/main/java/com/wlj/base/web/CallWebserviceImp.java
new file mode 100755
index 0000000..afadf4f
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/CallWebserviceImp.java
@@ -0,0 +1,17 @@
+package com.wlj.base.web;
+
+import org.json.JSONObject;
+
+import com.wlj.base.bean.Base;
+
+public class CallWebserviceImp {
+
+ public JSONObject getWebServerInfo(Base baseWebModle) {
+
+
+
+ return null;
+ }
+
+
+}
diff --git a/base/src/main/java/com/wlj/base/web/EnAes.java b/base/src/main/java/com/wlj/base/web/EnAes.java
new file mode 100755
index 0000000..b239db8
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/EnAes.java
@@ -0,0 +1,145 @@
+package com.wlj.base.web;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+public class EnAes implements Encrpt{
+
+ public static final String VIPARA = "0102030405060708";
+ public static final String bm = "UTF-8";
+
+ private Cipher cipher = null;
+
+ public EnAes(){
+ try {
+// cipher = Cipher.getInstance("AES");
+
+// cipher = Cipher.getInstance("AES/CBC/NoPadding");
+// cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+// cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
+// cipher = Cipher.getInstance("AES/CFB/NoPadding");
+// cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
+// cipher = Cipher.getInstance("AES/CFB/ISO10126Padding");
+// cipher = Cipher.getInstance("AES/ECB/NoPadding");
+ cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+// cipher = Cipher.getInstance("AES/ECB/ISO10126Padding");
+// cipher = Cipher.getInstance("AES/OFB/NoPadding");
+// cipher = Cipher.getInstance("AES/OFB/PKCS5Padding");
+// cipher = Cipher.getInstance("AES/OFB/ISO10126Padding");
+// cipher = Cipher.getInstance("AES/PCBC/NoPadding");
+// cipher = Cipher.getInstance("AES/PCBC/PKCS5Padding");
+// cipher = Cipher.getInstance("AES/PCBC/ISO10126Padding");
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (NoSuchPaddingException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param cleartext
+ * @param key 16bytes 的key
+ * @return
+ * @throws Exception
+ */
+ public String encrypt(String cleartext,String key)
+ throws Exception {
+ byte[] rawKey = null;
+ if(key.length() >= 16){
+ rawKey = key.substring(0, 16).getBytes();
+ }else{
+ rawKey = key.getBytes();
+ }
+ byte[] result = encrypt(rawKey, cleartext.getBytes());
+ return toHex(result);
+ }
+ /**
+ *
+ * @param cleartext
+ * @param key 16bytes 的key
+ * @return
+ * @throws Exception
+ */
+ public String decrypt(String encrypted,String key)
+ throws Exception {
+ byte[] rawKey = null;
+ if(key.length() > 16){
+ rawKey = key.substring(0, 16).getBytes();
+ }else{
+ rawKey = key.getBytes();
+ }
+ byte[] enc = toByte(encrypted);
+ byte[] result = decrypt(rawKey, enc);
+ return new String(result);
+ }
+
+ private byte[] getRawKey(byte[] seed) throws Exception {
+ KeyGenerator kgen = KeyGenerator.getInstance("AES");
+ SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
+ sr.setSeed(seed);
+ kgen.init(128, sr); // 192 and 256 bits may not be available
+ SecretKey skey = kgen.generateKey();
+ byte[] raw = skey.getEncoded();
+ return raw;
+ }
+
+ private byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
+ SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+ cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
+ byte[] encrypted = cipher.doFinal(clear);
+ return encrypted;
+ }
+
+ private byte[] decrypt(byte[] raw, byte[] encrypted)
+ throws Exception {
+ SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+ cipher.init(Cipher.DECRYPT_MODE, skeySpec);
+ byte[] decrypted = cipher.doFinal(encrypted);
+ return decrypted;
+ }
+
+ public String toHex(String txt) {
+ return toHex(txt.getBytes());
+ }
+
+ public String fromHex(String hex) {
+ return new String(toByte(hex));
+ }
+
+ public byte[] toByte(String hexString) {
+ int len = hexString.length() / 2;
+ byte[] result = new byte[len];
+ for (int i = 0; i < len; i++)
+ result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
+ 16).byteValue();
+ return result;
+ }
+
+ public String toHex(byte[] buf) {
+ if (buf == null)
+ return "";
+ StringBuilder result = new StringBuilder(2 * buf.length);
+ for (int i = 0; i < buf.length; i++) {
+ appendHex(result, buf[i]);
+ }
+ return result.toString();
+ }
+
+ private final static String HEX = "0123456789ABCDEF";
+
+ private void appendHex(StringBuilder sb, byte b) {
+ sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ }
+
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/web/Encrpt.java b/base/src/main/java/com/wlj/base/web/Encrpt.java
new file mode 100755
index 0000000..4b877e3
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/Encrpt.java
@@ -0,0 +1,10 @@
+package com.wlj.base.web;
+
+
+
+public interface Encrpt {
+
+ public String encrypt(String inputStr, String key) throws Exception;
+
+ public String decrypt(String inputStr, String key) throws Exception;
+}
diff --git a/base/src/main/java/com/wlj/base/web/HttpGet.java b/base/src/main/java/com/wlj/base/web/HttpGet.java
new file mode 100755
index 0000000..d9192fa
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/HttpGet.java
@@ -0,0 +1,72 @@
+package com.wlj.base.web;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+/**
+ *
+ * @author ly
+ *
+ */
+public class HttpGet{
+
+ private String urlStr ;
+ private StringBuilder paremeter;
+ private String charset = null;
+ /**
+ *
+ * @param urlStr url地址
+ * @throws IOException 如果这个报错就是连接根本没打开
+ */
+ public HttpGet(String urlStr) throws IOException{
+ charset = "utf-8";
+ this.urlStr = urlStr;
+ paremeter = new StringBuilder();
+ }
+ /**
+ *
+ * @param urlStr url地址
+ * @throws IOException 如果这个报错就是连接根本没打开
+ */
+ public HttpGet(String urlStr,String charset) throws IOException{
+ if(charset == null){
+ charset = "utf-8";
+ }else{
+ this.charset = charset;
+ }
+ this.urlStr = urlStr;
+ paremeter = new StringBuilder();
+ }
+
+ public String getResult() throws IOException{
+ if(paremeter != null && paremeter.length()>1){
+ paremeter = paremeter.deleteCharAt(paremeter.length()-1);
+ this.urlStr = this.urlStr +"?"+paremeter;
+ }
+
+ URL url = new URL(this.urlStr);
+ HttpURLConnection openConnection = (HttpURLConnection) url.openConnection();
+ openConnection.setConnectTimeout(10000);
+ openConnection.setReadTimeout(10000);
+
+ InputStream inputStream = null;
+ ByteArrayOutputStream outByteArray = new ByteArrayOutputStream();
+ inputStream = openConnection.getInputStream();
+ int b;
+ while (inputStream != null && (b = inputStream.read()) != -1) {
+ outByteArray.write(b);
+ }
+ byte[] returnByte = outByteArray.toByteArray();
+ return new String(returnByte,charset);
+ }
+
+ public void addParemeter(String name,String value){
+ paremeter.append(name).append("=").append(value).append("&");
+ }
+ public void addParemeterEncoder(String name,String value){
+ paremeter.append(name).append("=").append(URLEncoder.encode(value)).append("&");
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/web/HttpPost.java b/base/src/main/java/com/wlj/base/web/HttpPost.java
new file mode 100755
index 0000000..106d9d6
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/HttpPost.java
@@ -0,0 +1,242 @@
+package com.wlj.base.web;
+
+
+import com.orhanobut.logger.Logger;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author ly
+ */
+public class HttpPost {
+
+ private JSONObject jSONObjectParemeter;
+ private URL url;
+ private URLConnection openConnection;
+ private StringBuilder paremeter = new StringBuilder();
+ private String charset = null;
+
+
+ private static Map cookies = new HashMap();
+
+ public HttpPost(String paramString) throws IOException {
+ this(new URL(paramString));
+ }
+
+ /**
+ * @param url url地址
+ * @throws IOException 如果这个报错就是连接根本没打开
+ */
+ public HttpPost(URL url, String charset) throws IOException {
+ if (charset == null) {
+ charset = "utf-8";
+ } else {
+ this.charset = charset;
+ }
+
+ this.url = url;
+ this.openConnection = url.openConnection();
+ this.openConnection.setDoOutput(true);
+ this.openConnection.setDoInput(true);
+ this.openConnection.setConnectTimeout(10000);
+ this.openConnection.setReadTimeout(10000);
+ this.jSONObjectParemeter = new JSONObject();
+ this.charset = charset;
+
+ }
+
+ /**
+ * @param url url地址
+ * @throws IOException 如果这个报错就是连接根本没打开
+ */
+ public HttpPost(URL url) throws IOException {
+ this.charset = "utf-8";
+ this.url = url;
+ this.openConnection = url.openConnection();
+ this.openConnection.setDoOutput(true);
+ this.openConnection.setDoInput(true);
+ this.openConnection.setConnectTimeout(10000);
+ this.openConnection.setReadTimeout(10000);
+ this.jSONObjectParemeter = new JSONObject();
+ }
+
+ public void addParemeter(String paramString, Object paramObject) {
+
+ if (paramString == null) {
+ this.paremeter.append(paramObject).append("&");
+ return;
+ }
+ this.paremeter.append(paramString).append("=").append(URLEncoder.encode(paramObject + "")).append("&");
+ try {
+ this.jSONObjectParemeter.put(paramString, paramObject);
+ return;
+ } catch (JSONException localJSONException) {
+ localJSONException.printStackTrace();
+ }
+ }
+
+ public void addRequestProperty(String key, String value) {
+ openConnection.addRequestProperty(key, value);
+ }
+
+ public InputStream getInputStream()throws IOException {
+ InputStream inputStream = null;
+
+ if (this.paremeter.length() > 1) {
+ this.paremeter = this.paremeter.deleteCharAt(-1 + this.paremeter.length());
+ }
+ StringBuilder sb = new StringBuilder();
+ if (cookies != null) {
+ Iterator localIterator2 = cookies.keySet().iterator();
+ while (localIterator2.hasNext()) {
+ String str2 = (String) localIterator2.next();
+ String str3 = (String) cookies.get(str2);
+ sb.append(str2 + "=" + str3 + "; ");
+ }
+ }
+
+ try {
+ if (sb.toString().trim().length() > 0) {
+ this.openConnection.setRequestProperty("Cookie", sb.toString());
+ }
+ OutputStreamWriter localOutputStreamWriter = new OutputStreamWriter(this.openConnection.getOutputStream(), this.charset);
+
+ localOutputStreamWriter.write(this.paremeter.toString());
+ localOutputStreamWriter.flush();
+ localOutputStreamWriter.close();
+
+ if (cookies != null) {
+ Map> headerFields = openConnection.getHeaderFields();
+ if (headerFields != null) {
+ List list = headerFields.get("Set-Cookie");
+ if (list != null) {
+ for (String string2 : list) {
+ String[] substring = string2.substring(0, string2.indexOf(";")).split("=");
+ cookies.put(substring[0], substring[1]);
+ }
+ }
+ }
+ }
+
+ inputStream = openConnection.getInputStream();
+
+ } catch (IOException e) {
+ inputStream = ((HttpURLConnection) openConnection).getErrorStream();
+
+ throw e;
+ }
+ return inputStream;
+
+ }
+
+ /**
+ * @return post的返回值
+ * @throws IOException 获取结果报错
+ */
+ public String getResult() throws IOException {
+ OutputStreamWriter outputStream = null;
+ InputStream inputStream = null;
+ ByteArrayOutputStream outByteArray = new ByteArrayOutputStream();
+ if (paremeter.length() > 1) {
+ paremeter = paremeter.deleteCharAt(paremeter.length() - 1);
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ if (cookies != null) {
+ Set keySet = cookies.keySet();
+ for (String string : keySet) {
+ String string2 = cookies.get(string);
+ sb.append(string + "=" + string2 + "; ");
+ }
+ }
+
+ byte[] returnByte = null;
+ try {
+ if (sb != null && sb.toString().trim().length() > 0) {
+ openConnection.setRequestProperty("Cookie", sb.toString());
+ }
+ outputStream = new OutputStreamWriter(openConnection.getOutputStream(), charset);
+ outputStream.write(paremeter.toString());
+ outputStream.flush();
+ outputStream.close();
+ //System.out.print(openConnection.getHeaderField("Set-Cookie"));
+
+// System.out.println(openConnection.getHeaderFields());
+
+ if (cookies != null) {
+ Map> headerFields = openConnection.getHeaderFields();
+ if (headerFields != null) {
+ List list = headerFields.get("Set-Cookie");
+ if (list != null) {
+ for (String string2 : list) {
+ String[] substring = string2.substring(0, string2.indexOf(";")).split("=");
+ cookies.put(substring[0], substring[1]);
+
+// Logger.e(cookies.toString());
+ }
+ }
+ }
+ }
+
+ inputStream = openConnection.getInputStream();
+ int b;
+ while (inputStream != null && (b = inputStream.read()) != -1) {
+ outByteArray.write(b);
+ }
+ returnByte = outByteArray.toByteArray();
+ } catch (IOException e) {
+ inputStream = ((HttpURLConnection) openConnection).getErrorStream();
+ int b;
+ while (inputStream != null && (b = inputStream.read()) != -1) {
+ outByteArray.write(b);
+ }
+ returnByte = outByteArray.toByteArray();
+ throw e;
+ } finally {
+ outByteArray.close();
+ if (outputStream != null) {
+ outputStream.close();
+ }
+ if (inputStream != null) {
+ inputStream.close();
+ }
+
+ }
+ return new String(returnByte, charset);
+ }
+
+
+ public JSONObject getJSONObjectParemeter()
+ {
+
+ return this.jSONObjectParemeter;
+ }
+
+ public StringBuilder getParemeter()
+ {
+
+ return this.paremeter;
+ }
+
+ public URL getUrl()
+ {
+
+ return this.url;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/web/Md5Util.java b/base/src/main/java/com/wlj/base/web/Md5Util.java
new file mode 100755
index 0000000..7b107f0
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/Md5Util.java
@@ -0,0 +1,82 @@
+package com.wlj.base.web;
+
+
+import java.security.MessageDigest;
+import java.util.UUID;
+
+public class Md5Util {
+
+ public final static String MD5(String s) {
+ char hexDigits[] = { '2', 'b', '3', '0', '8', 'd', 'f', '6', '1', 'a',
+ '9', '5', 'c', '7', '4', 'e' };
+ try {
+ byte[] strTemp = s.getBytes();
+ MessageDigest mdTemp = MessageDigest.getInstance("MD5");
+ mdTemp.update(strTemp);
+ byte[] md = mdTemp.digest();
+ int j = md.length;
+ char str[] = new char[j * 2];
+ int k = 0;
+ for (int i = 0; i < j; i++) {
+ byte byte0 = md[i];
+ str[k++] = hexDigits[byte0 >>> 4 & 0xf];
+ str[k++] = hexDigits[byte0 & 0xf];
+ }
+ return new String(str);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public final static String MD5Normal(String s) {
+ char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f' };
+ try {
+ byte[] strTemp = s.getBytes("utf-8");
+ MessageDigest mdTemp = MessageDigest.getInstance("MD5");
+ mdTemp.update(strTemp);
+ byte[] md = mdTemp.digest();
+ int j = md.length;
+ char str[] = new char[j * 2];
+ int k = 0;
+ for (int i = 0; i < j; i++) {
+ byte byte0 = md[i];
+ str[k++] = hexDigits[byte0 >>> 4 & 0xf];
+ str[k++] = hexDigits[byte0 & 0xf];
+ }
+
+ return new String(str);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ public final static String MD5Normal(byte[] strTemp) {
+ char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f' };
+ try {
+ MessageDigest mdTemp = MessageDigest.getInstance("MD5");
+ mdTemp.update(strTemp);
+ byte[] md = mdTemp.digest();
+ int j = md.length;
+ char str[] = new char[j * 2];
+ int k = 0;
+ for (int i = 0; i < j; i++) {
+ byte byte0 = md[i];
+ str[k++] = hexDigits[byte0 >>> 4 & 0xf];
+ str[k++] = hexDigits[byte0 & 0xf];
+ }
+
+ return new String(str);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+
+ public static void main(String[] args) {
+ String md5Normal = Md5Util.MD5Normal(UUID.randomUUID().toString());
+ String luishui = System.currentTimeMillis()+md5Normal.substring(17);
+ System.out.println(luishui);
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/web/MsgContext.java b/base/src/main/java/com/wlj/base/web/MsgContext.java
new file mode 100755
index 0000000..9fccac6
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/MsgContext.java
@@ -0,0 +1,27 @@
+package com.wlj.base.web;
+
+
+public class MsgContext {
+
+ public static final int request_false = 100;
+ public static final int request_false2 = 1;
+
+ public static final int request_success = 200;
+ public static final int request_success2 = 2;
+
+ public static final int request_system_error = 300;
+ public static final int request_system_error2 = 3;
+
+ public static final String key_page = "page";
+ public static final String key_pageSize = "pageSize";
+ public static final int pageSize = 20;
+
+ public static final String login = "login";
+ public static final String key_username = "username";
+ public static final String key_pwd = "pwd";
+
+ public static final String home_banner = "57fca5edef722c216b767c98";
+ public static final String home_news = "57fca5ffef722c216b767c99";
+ public static final String home_hot = "57fca56def722c216b767c91";
+ public static final String home_newest ="5812ef5478e0802052dd7a2f";
+}
diff --git a/base/src/main/java/com/wlj/base/web/RequestWebClient.java b/base/src/main/java/com/wlj/base/web/RequestWebClient.java
new file mode 100755
index 0000000..06398ae
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/RequestWebClient.java
@@ -0,0 +1,213 @@
+package com.wlj.base.web;
+
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.util.Map;
+import java.util.Set;
+
+import org.json.JSONObject;
+
+import com.wlj.base.bean.Base;
+import com.wlj.base.bean.BaseList;
+import com.wlj.base.util.Log;
+import com.wlj.base.util.RequestException;
+
+
+/**
+ *
+ * 添加请求参数 Map params 处理返回参数
+ *
+ * @author wlj
+ *
+ */
+public class RequestWebClient {
+
+ private static RequestWebClient requestWebClient;
+ public static String key_page = "page";
+ public static String key_pageSize = "pageSize";
+
+
+ public static RequestWebClient getInstall() {
+ if (requestWebClient == null) {
+ requestWebClient = new RequestWebClient();
+ }
+ return requestWebClient;
+ }
+
+// public User Login(User u) throws Exception {
+//
+// String pwd = u.getPsw();
+//
+// String randCode = u.getRandCode();
+//
+// HttpPost hp = new HttpPost(new URL(URLs.login ));
+//
+// if (randCode != null && !"".equals(randCode)) {// 验证码登录
+// hp.addParemeter("randCode", randCode);
+// hp.addParemeter("username", u.getName());
+// String psw = u.getPsw();
+// if(!"".equals(psw)){
+// hp.addParemeter("pwd_change", psw);
+// }
+//
+// } else {
+// String rand = System.currentTimeMillis() + "";
+// hp.addParemeter("username", u.getName());
+// hp.addParemeter("rand", rand);
+// hp.addParemeter("pwd",Md5Util.MD5Normal(Md5Util.MD5Normal(pwd) + rand));
+// }
+//
+// String result = hp.getResult();
+// Log.e("Login", result);
+// JSONObject jSONObject = new JSONObject(result);
+// String state = jSONObject.getString("state");
+// // {"type":3,"key":"de3572e4391c92db60ad4ab4","state":2}
+// if (MsgContext.request_success.equals(state)) {
+//
+// return (User) u.parse(jSONObject);
+// } else if (MsgContext.request_false.equals(state)
+// || MsgContext.request_system_error.equals(state)) {
+//
+// throw new RequestException(jSONObject.getString("description"));
+// }
+// throw new RequestException("获取数据失败");
+// }
+
+// public String getLoginRand(String phone) throws Exception {
+//
+// HttpPost hp = new HttpPost(new URL( URLs.getLoginRand));
+//
+// hp.addParemeter("username", phone);
+//
+// String result = hp.getResult();
+// Log.e("getLoginRand", result);
+// JSONObject jSONObject = new JSONObject(result);
+//
+// String state = jSONObject.getString("state");
+//
+// if (MsgContext.request_success.equals(state)) {
+//
+// return jSONObject.getString("description");
+// } else if (MsgContext.request_false.equals(state)
+// || MsgContext.request_system_error.equals(state)) {
+//
+// throw new RequestException(jSONObject.getString("description"));
+// }
+// throw new RequestException("获取数据失败");
+// }
+ private JSONObject request(Map map,String key,String name) throws Exception {
+ String request_data = null;
+
+ if (map == null)
+ throw new RequestException("参数为空");
+ Object url = map.get("url");
+ map.remove("url");
+ if (url == null)
+ throw new RequestException("地址为空");
+
+ //是否需要加密
+ if (map.containsKey("bujiami")) {
+ // map 有不加密 key
+ HttpPost hp = new HttpPost(new URL(url + ""));
+
+ Set set = map.keySet();
+ for (String string : set) {
+ hp.addParemeter(string, map.get(string)+"");
+ }
+
+ if (map.get(key_page) != null) {
+ hp.addParemeter(key_page, map.get(key_page)+"");
+
+ if (map.get(key_pageSize) == null) {
+ hp.addParemeter(key_pageSize, MsgContext.pageSize + "");
+ }
+ }
+
+// if (name != null) {
+ String login_rand = "" + System.currentTimeMillis();
+
+ String login_mac = Md5Util.MD5Normal(key + login_rand);
+ hp.addParemeter("login_name", name);
+ hp.addParemeter("login_rand", login_rand);
+ hp.addParemeter("login_mac", login_mac);
+// }
+ request_data = hp.getResult();
+
+ } else {
+ // map 没有不加密 key,不管vaule是什么,都认为需要加密
+ JSONObject json = new JSONObject();
+
+ Set set = map.keySet();
+ for (String string : set) {
+ json.put(string, map.get(string));
+ }
+
+ if (map.get(key_page) != null) {
+ json.put(key_page, map.get(key_page));
+
+ if (map.get(key_pageSize) == null) {
+ json.put(key_pageSize, MsgContext.pageSize + "");
+ }
+ }
+
+ request_data = BaseWebMain.request_data(url + "", key, name,
+ json.toString());
+ }
+
+ if (request_data == null) {
+ throw new RequestException("返回数据为空");
+ }
+ Log.w(url.toString().substring(url.toString().lastIndexOf("/")),request_data);
+
+ return new JSONObject(request_data);
+ }
+
+ /**
+ * 自己定义返回
+ *
+ * @param base 为null 则反回null
+ * @param map
+ * @throws Exception
+ */
+ public BaseList Request(Map map, Base cla,String key,String name)throws Exception {
+ JSONObject jsonObject = null;
+ try {
+ jsonObject = request(map, key, name);
+ } catch (Exception e) {
+ if(e instanceof FileNotFoundException){
+ throw new RequestException("地址错误(FileNotFoundException)");
+ }else{
+ throw e;
+ }
+ }
+// {"state":"3","description":"系统错误","message":"系统错误"}
+ int state = jsonObject.optInt("statusCode");
+ if(state == 0){
+ state = jsonObject.optInt("state");
+ }
+ if (MsgContext.request_success == state || MsgContext.request_success2 == state) {
+ if (cla == null) {
+ return null;
+ }
+ BaseList projectList = new BaseList();
+ long millis = System.currentTimeMillis();
+
+ projectList.parse(jsonObject, cla);
+ Log.d("dd", (System.currentTimeMillis() - millis) + " parse");
+ return projectList;
+ } else
+ if (MsgContext.request_false == state
+ || MsgContext.request_system_error == state
+ || MsgContext.request_system_error2 == state)
+ {
+ String optString = jsonObject.optString("message");
+ if("".equals(optString)){
+ optString = jsonObject.optString("description");
+ }
+ throw new RequestException(optString);
+ }
+
+ throw new RequestException("数据解析失败");
+
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/web/asyn/AsyncCall.java b/base/src/main/java/com/wlj/base/web/asyn/AsyncCall.java
new file mode 100644
index 0000000..26b14d3
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/asyn/AsyncCall.java
@@ -0,0 +1,169 @@
+package com.wlj.base.web.asyn;
+
+import android.app.Activity;
+import android.content.DialogInterface;
+import android.os.AsyncTask;
+
+import com.orhanobut.logger.Logger;
+import com.wlj.base.bean.Base;
+import com.wlj.base.bean.BaseList;
+import com.wlj.base.util.AppContext;
+import com.wlj.base.util.RequestException;
+import com.wlj.base.util.UIHelper;
+
+import java.net.SocketTimeoutException;
+import java.util.List;
+
+public class AsyncCall
+ extends AsyncTask {
+ private Activity activity;
+ private AsyncRequestModle asyncRequestModle;
+ private boolean autoToLoginPage;
+ private int lastpage;
+ private OnAsyncBackListener onBackListener;
+ private boolean showLoading;
+ private boolean showToast;
+
+ public AsyncCall(AsyncRequestModle paramAsyncRequestModle) {
+ this.showToast = true;
+ this.autoToLoginPage = true;
+ this.showLoading = paramAsyncRequestModle.isShowLoading();
+ this.autoToLoginPage = paramAsyncRequestModle.isAutoToLoginPage();
+ this.asyncRequestModle = paramAsyncRequestModle;
+ this.activity = paramAsyncRequestModle.getActivity();
+ }
+
+
+ public Object doInBackground(Void... paramVarArgs) {
+
+ try {
+
+ BaseList localObject = AsyncRequestWebClient.getInstall().RequestConnected(this.asyncRequestModle);
+
+ return localObject;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return e;
+ }
+
+ }
+
+ public boolean isComplate() {
+
+ if (this.asyncRequestModle.getHttpPost().getJSONObjectParemeter().optInt("page") >= this.lastpage) {
+ return true;
+ }
+ return false;
+ }
+
+ public void onCancelled() {
+ super.onCancelled();
+ Logger.e("onCancelled" );
+ }
+
+ public void onCancelled(Object paramObject) {
+ super.onCancelled(paramObject);
+ Logger.e("onCancelled ~~~"+ paramObject );
+ }
+
+ public void onPostExecute(Object paramObject) {
+ super.onPostExecute(paramObject);
+
+ String str = null;
+
+ if ((paramObject instanceof Exception)) {
+ // 异常
+ Exception localException = (Exception) paramObject;
+ str = localException.getMessage();
+
+ if (this.showToast) {
+ //显示异常
+ if ((localException instanceof SocketTimeoutException)) {
+ UIHelper.toastMessage(AppContext.getAppContext(), " 链接超时");
+ }else {
+ UIHelper.toastMessage(AppContext.getAppContext(), str);
+ }
+ } else {
+ //把异常返回前段
+ if ((this.autoToLoginPage) && (str != null) && ((str.contains("登录")) || (str.contains("登陆")))) {
+// new GOTOHelp(this.activity).Go(AppConfig.getInstall().getLoginClass());
+ AppContext.getAppContext().loginOut();
+ }
+ if (this.onBackListener != null) {
+ this.onBackListener.fail(localException);
+ }
+ }
+
+ }
+// 返回正常数据 BaseList / base
+ if (this.onBackListener != null) {
+ if ((paramObject instanceof BaseList)) {
+
+ BaseList localBaseList = (BaseList) paramObject;
+ List localList = localBaseList.getList();
+ Base localBase = localBaseList.getBaseData();
+ this.lastpage = localBaseList.getLastpage();
+
+ if ((localList != null) || (localBase != null)) {
+ this.onBackListener.OnAsyncBack(localList, localBase, this.asyncRequestModle.getType());
+ } else {
+ UIHelper.toastMessage(AppContext.getAppContext(), "数据为空");
+ }
+ } else if ((paramObject instanceof Base)) {
+ this.onBackListener.OnAsyncBack(null, (Base) paramObject, this.asyncRequestModle.getType());
+ }
+ }
+
+ UIHelper.closeProgressbar();
+ }
+
+ public void onPreExecute() {
+ if ((!showLoading) || (this.activity == null)) {
+ return;
+ }
+
+ UIHelper.showProgressbar(this.activity, new DialogInterface.OnCancelListener() {
+
+ public void onCancel(DialogInterface paramAnonymousDialogInterface) {
+
+ AsyncCall.this.cancel(true);
+ }
+ });
+
+ }
+
+ public void onProgressUpdate(Integer... paramVarArgs) {
+ super.onProgressUpdate(paramVarArgs);
+ }
+
+ public void setAutoToLoginPage(boolean paramBoolean) {
+
+ this.autoToLoginPage = paramBoolean;
+ }
+
+ public void setOnAsyncBackListener(OnAsyncBackListener paramOnAsyncBackListener) {
+
+ this.onBackListener = paramOnAsyncBackListener;
+ }
+
+ public void setShowLoading(boolean paramBoolean) {
+
+ this.showLoading = paramBoolean;
+ }
+
+ public void setShowToast(boolean paramBoolean) {
+
+ this.showToast = paramBoolean;
+ }
+
+ public static abstract interface OnAsyncBackListener {
+ public abstract void OnAsyncBack(List paramList, Base paramBase, int paramInt);
+
+ public abstract void fail(Exception paramException);
+ }
+
+ public static abstract interface callWeb {
+ public abstract AsyncCall Request();
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/web/asyn/AsyncRequestModle.java b/base/src/main/java/com/wlj/base/web/asyn/AsyncRequestModle.java
new file mode 100644
index 0000000..e4187cf
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/asyn/AsyncRequestModle.java
@@ -0,0 +1,166 @@
+package com.wlj.base.web.asyn;
+
+import android.app.Activity;
+import android.util.Base64;
+
+import com.wlj.base.bean.Base;
+import com.wlj.base.util.AppContext;
+import com.wlj.base.web.HttpPost;
+import java.io.Serializable;
+import org.json.JSONObject;
+
+public class AsyncRequestModle
+ implements Serializable
+{
+ private static final long serialVersionUID = -7241890269318232468L;
+ private Activity activity;
+ private boolean autoToLoginPage = true;
+ private String cachekey;
+ private HttpPost httpPost;
+ private boolean jiami;
+ private BaseAsyncModle parserBase;
+ private Class> parserCla;
+ private boolean refresh = true;
+ private boolean save = true;
+ private boolean showLoading;
+ private int type;
+
+ public AsyncRequestModle() {}
+
+ public Activity getActivity()
+ {
+
+ return this.activity;
+ }
+
+ public String getCachekey()
+ {
+
+ String str = this.httpPost.getJSONObjectParemeter().toString();
+ int i = 10;
+ if (str.length() < 10) {
+ i = str.length();
+ }
+ return Base64.encodeToString((AppContext.getAppContext().getProperty("type") + "_" + AppContext.getAppContext().getProperty("name") + "_" + getParserCla().getSimpleName() + "_" + this.cachekey + "_" + str.substring(0, i)).getBytes(), 0);
+ }
+
+ public HttpPost getHttpPost()
+ {
+
+ return this.httpPost;
+ }
+
+ public BaseAsyncModle getParserBase()
+ {
+
+ return this.parserBase;
+ }
+
+ public Class> getParserCla()
+ {
+
+ return this.parserCla;
+ }
+
+ public int getType()
+ {
+
+ return this.type;
+ }
+
+ public boolean isAutoToLoginPage()
+ {
+
+ return this.autoToLoginPage;
+ }
+
+ public boolean isJiami()
+ {
+
+ return this.jiami;
+ }
+
+ public boolean isRefresh()
+ {
+
+ return this.refresh;
+ }
+
+ public boolean isSave()
+ {
+
+ return this.save;
+ }
+
+ public boolean isShowLoading()
+ {
+
+ return this.showLoading;
+ }
+
+ public void setActivity(Activity paramActivity)
+ {
+
+ this.activity = paramActivity;
+ }
+
+ public void setAutoToLoginPage(boolean paramBoolean)
+ {
+
+ this.autoToLoginPage = paramBoolean;
+ }
+
+ public void setCachekey(String paramString)
+ {
+
+ this.cachekey = paramString;
+ }
+
+ public void setHttpPost(HttpPost paramHttpPost)
+ {
+
+ this.httpPost = paramHttpPost;
+ }
+
+ public void setJiami(boolean paramBoolean)
+ {
+
+ this.jiami = paramBoolean;
+ }
+
+ public void setParserBase(BaseAsyncModle paramBaseAsyncModle)
+ {
+
+ this.parserBase = paramBaseAsyncModle;
+ }
+
+ public void setParserCla(Class> paramClass)
+ {
+
+ this.parserCla = paramClass;
+ }
+
+ public void setRefresh(boolean paramBoolean)
+ {
+
+ this.refresh = paramBoolean;
+ }
+
+ public void setSave(boolean paramBoolean)
+ {
+
+ this.save = paramBoolean;
+ }
+
+ public void setShowLoading(boolean paramBoolean)
+ {
+
+ this.showLoading = paramBoolean;
+ }
+
+ public void setType(int paramInt)
+ {
+
+ this.type = paramInt;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/web/asyn/AsyncRequestWebClient.java b/base/src/main/java/com/wlj/base/web/asyn/AsyncRequestWebClient.java
new file mode 100644
index 0000000..ce20b39
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/asyn/AsyncRequestWebClient.java
@@ -0,0 +1,132 @@
+package com.wlj.base.web.asyn;
+
+import com.orhanobut.logger.Logger;
+import com.wlj.base.bean.BaseList;
+import com.wlj.base.util.AppContext;
+import com.wlj.base.util.RequestException;
+import com.wlj.base.web.HttpPost;
+import com.wlj.base.web.Md5Util;
+import com.wlj.base.web.MsgContext;
+
+import java.io.FileNotFoundException;
+
+import org.json.JSONObject;
+
+public class AsyncRequestWebClient {
+ private static AsyncRequestWebClient requestWebClient;
+
+ public AsyncRequestWebClient() {
+ }
+
+
+ private BaseList callWeb(AsyncRequestModle paramAsyncRequestModle)
+ throws Exception {
+
+ try {
+ JSONObject localJSONObject = encryptionCall(paramAsyncRequestModle);
+ return parse(localJSONObject, paramAsyncRequestModle);
+ } catch (Exception localException) {
+ if ((localException instanceof FileNotFoundException)) {
+ throw new RequestException("(FileNotFoundException)");
+ }
+ throw localException;
+ }
+ }
+
+ private JSONObject encryptionCall(AsyncRequestModle paramAsyncRequestModle)
+ throws Exception {
+ HttpPost localHttpPost = paramAsyncRequestModle.getHttpPost();
+ if (localHttpPost == null) {
+ throw new RequestException("HttpPost为空");
+ }
+ String url = localHttpPost.getUrl().getPath();
+
+ String str2 = url.substring(url.lastIndexOf("/"), url.length());
+
+ String parem = localHttpPost.getJSONObjectParemeter().toString();
+// Logger.w("参数" + str2 +": "+ parem);
+
+ if (paramAsyncRequestModle.isJiami()) {
+ Encrpt.encrypt(paramAsyncRequestModle, localHttpPost);
+ } else {
+ //不加密
+// String key = AppContext.getAppContext().getProperty("key");
+// String name = AppContext.getAppContext().getProperty("name");
+// String cur = "" + System.currentTimeMillis();
+// String mac = Md5Util.MD5Normal(key + cur);
+// localHttpPost.addParemeter("login_name", name);
+// localHttpPost.addParemeter("login_rand", cur);
+// localHttpPost.addParemeter("login_mac", mac);
+ }
+
+ String str8 = localHttpPost.getResult();
+ Logger.w(str2 +":"+ parem + " \n " +str8);
+
+ return new JSONObject(str8);
+
+ }
+
+ public static AsyncRequestWebClient getInstall() {
+
+ if (requestWebClient == null) {
+ requestWebClient = new AsyncRequestWebClient();
+ }
+ return requestWebClient;
+ }
+
+ private BaseList parse(JSONObject paramJSONObject, AsyncRequestModle paramAsyncRequestModle)
+ throws Exception {
+ int i = paramJSONObject.optInt("statusCode");
+ if (i == 0) {
+ i = paramJSONObject.optInt("state");
+ }
+ if ((MsgContext.request_success == i) || (MsgContext.request_success2 == i)) {
+ BaseAsyncModle localBaseAsyncModle = paramAsyncRequestModle.getParserBase();
+ if (localBaseAsyncModle == null) {
+ return new BaseList().parse(paramJSONObject, paramAsyncRequestModle.getParserCla());
+ }
+ localBaseAsyncModle.parseThis(paramJSONObject.optJSONObject("data"));
+ BaseList localBaseList = new BaseList();
+ localBaseList.setBaseData(localBaseAsyncModle);
+ return localBaseList;
+ }
+ if ((MsgContext.request_false2 == i) || (MsgContext.request_false == i) || (MsgContext.request_system_error2 == i)
+ || (MsgContext.request_system_error == i)) {
+ String str = paramJSONObject.optString("message");
+ if ("".equals(str)) {
+ str = paramJSONObject.optString("description");
+ }
+ throw new RequestException(str);
+ }
+ throw new RequestException("未知异常");
+ }
+
+ public BaseList Request(AsyncRequestModle paramAsyncRequestModle)
+ throws Exception {
+
+ String str = paramAsyncRequestModle.getCachekey();
+ AppContext localAppContext = AppContext.getAppContext();
+ Logger.w("key", new Object[]{str});
+ BaseList localBaseList = null;
+ if ((!localAppContext.isReadDataCache(str)) || (paramAsyncRequestModle.isRefresh())) {
+ localBaseList = RequestConnected(paramAsyncRequestModle);
+ if ((localBaseList != null) && (paramAsyncRequestModle.isSave())) {
+ localAppContext.saveObject(localBaseList, str);
+ }
+ }
+ return localBaseList;
+ }
+
+ public BaseList RequestConnected(AsyncRequestModle paramAsyncRequestModle)
+ throws Exception {
+ AppContext localAppContext = AppContext.getAppContext();
+ if (localAppContext.isNetworkAvailable()) {
+ return callWeb(paramAsyncRequestModle);
+ }
+ BaseList localBaseList = (BaseList) localAppContext.readObject(paramAsyncRequestModle.getCachekey());
+ if (localBaseList == null) {
+ throw new RequestException("数据为空");
+ }
+ return localBaseList;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/web/asyn/BaseAsyncModle.java b/base/src/main/java/com/wlj/base/web/asyn/BaseAsyncModle.java
new file mode 100644
index 0000000..3ad4a8c
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/asyn/BaseAsyncModle.java
@@ -0,0 +1,123 @@
+package com.wlj.base.web.asyn;
+
+import android.app.Activity;
+
+import com.wlj.base.bean.Base;
+import com.wlj.base.util.AppContext;
+import com.wlj.base.util.UIHelper;
+import com.wlj.base.web.HttpPost;
+
+import java.io.IOException;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public abstract class BaseAsyncModle extends Base implements AsyncCall.callWeb {
+ private static final long serialVersionUID = -764627344493414453L;
+ public transient Activity activity;
+ private int page = -1;
+ private int pageSize = 10;
+ private boolean refresh = true;
+
+
+ public BaseAsyncModle() {
+ }
+
+ public BaseAsyncModle(Activity paramActivity) {
+
+ this.activity = paramActivity;
+ }
+
+ public BaseAsyncModle(JSONObject jo) {
+ super(jo);
+ }
+
+ public AsyncCall Request() {
+ return Request(-1);
+ }
+
+ public AsyncCall Request(int type) {
+
+ try {
+ AsyncRequestModle localAsyncRequestModle = new AsyncRequestModle();
+ localAsyncRequestModle.setActivity(this.activity);
+ localAsyncRequestModle.setParserCla(getClass());
+ localAsyncRequestModle.setJiami(true);
+ localAsyncRequestModle.setRefresh(this.refresh);
+ if (type == -1) {
+ addRequestParemeter(localAsyncRequestModle);
+ }else{
+ localAsyncRequestModle.setType(type);
+ addRequestParemeter(localAsyncRequestModle, type);
+ }
+
+ HttpPost localHttpPost = localAsyncRequestModle.getHttpPost();
+ if (getPage() != -1) {
+ localHttpPost.addParemeter("page", Integer.valueOf(getPage()));
+ localHttpPost.addParemeter("pageSize", Integer.valueOf(getPageSize()));
+ }
+ AsyncCall localAsyncCall = new AsyncCall(localAsyncRequestModle);
+ localAsyncCall.execute();
+ return localAsyncCall;
+
+ } catch (IOException localIOException) {
+ localIOException.printStackTrace();
+ UIHelper.toastMessage(AppContext.getAppContext(), "请求异常");
+ }
+ return null;
+ }
+
+ public abstract void addRequestParemeter(AsyncRequestModle asRequestModle)
+ throws IOException;
+
+ public void addRequestParemeter(AsyncRequestModle asRequestModle, int type)
+ throws IOException {
+
+ }
+
+ public Activity getActivity() {
+
+ return this.activity;
+ }
+
+ public int getPage() {
+
+ return this.page;
+ }
+
+ public int getPageSize() {
+
+ return this.pageSize;
+ }
+
+ public AsyncCall getThisfromid() {
+
+ return null;
+ }
+
+ public boolean isRefresh() {
+
+ return this.refresh;
+ }
+
+ public BaseAsyncModle parseThis(JSONObject paramJSONObject)
+ throws JSONException {
+
+ return null;
+ }
+
+ public void setPage(int paramInt) {
+
+ this.page = paramInt;
+ }
+
+ public void setPageSize(int paramInt) {
+
+ this.pageSize = paramInt;
+ }
+
+ public void setRefresh(boolean paramBoolean) {
+
+ this.refresh = paramBoolean;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/web/asyn/Encrpt.java b/base/src/main/java/com/wlj/base/web/asyn/Encrpt.java
new file mode 100644
index 0000000..bd94855
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/web/asyn/Encrpt.java
@@ -0,0 +1,31 @@
+package com.wlj.base.web.asyn;
+
+import com.wlj.base.util.AppContext;
+import com.wlj.base.web.HttpPost;
+import com.wlj.base.web.Md5Util;
+
+public class Encrpt
+{
+ public static final Integer client_type_json = Integer.valueOf(2);
+ public static final Integer client_type_xml = Integer.valueOf(1);
+
+ public static void encrypt(AsyncRequestModle paramAsyncRequestModle, HttpPost paramHttpPost)
+ {
+
+ String str1 = AppContext.getAppContext().getProperty("key");
+ String str2 = AppContext.getAppContext().getProperty("name");
+ String str3 = AppContext.getAppContext().getProperty("type");
+ String str4 = System.currentTimeMillis() + "";
+ String str5 = Md5Util.MD5Normal(str1 + str4);
+ String str6 = paramHttpPost.getJSONObjectParemeter().toString();
+ String str7 = Md5Util.MD5Normal(str5 + str2 + str6);
+ paramHttpPost.addParemeter("name", str2);
+ paramHttpPost.addParemeter("randCode", str4);
+ paramHttpPost.addParemeter("encrpt", "enAes");
+ paramHttpPost.addParemeter("isEncryption", Boolean.FALSE.toString());
+ paramHttpPost.addParemeter("mode", client_type_json + "");
+ paramHttpPost.addParemeter("type", str3);
+ paramHttpPost.addParemeter("data", str6);
+ paramHttpPost.addParemeter("mac", str7);
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/widget/AutoScrollViewPager.java b/base/src/main/java/com/wlj/base/widget/AutoScrollViewPager.java
new file mode 100755
index 0000000..b3d0c5d
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/AutoScrollViewPager.java
@@ -0,0 +1,391 @@
+package com.wlj.base.widget;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+
+import com.wlj.base.util.Log;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.animation.Interpolator;
+
+/**
+ * Auto Scroll View Pager
+ *
+ * Basic Setting and Usage
+ * {@link #startAutoScroll()} start auto scroll, or {@link #startAutoScroll(int)} start auto scroll delayed
+ * {@link #stopAutoScroll()} stop auto scroll
+ * {@link #setInterval(long)} set auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}
+ *
+ *
+ * Advanced Settings and Usage
+ * {@link #setDirection(int)} set auto scroll direction
+ * {@link #setCycle(boolean)} set whether automatic cycle when auto scroll reaching the last or first item, default
+ * is true
+ * {@link #setSlideBorderMode(int)} set how to process when sliding at the last or first item
+ * {@link #setStopScrollWhenTouch(boolean)} set whether stop auto scroll when touching, default is true
+ *
+ *
+ * @author Trinea 2013-12-30
+ */
+public class AutoScrollViewPager extends ViewPager {
+
+ public static final int DEFAULT_INTERVAL = 1500;
+
+ public static final int LEFT = 0;
+ public static final int RIGHT = 1;
+
+ /** do nothing when sliding at the last or first item **/
+ public static final int SLIDE_BORDER_MODE_NONE = 0;
+ /** cycle when sliding at the last or first item **/
+ public static final int SLIDE_BORDER_MODE_CYCLE = 1;
+ /** deliver event to parent when sliding at the last or first item **/
+ public static final int SLIDE_BORDER_MODE_TO_PARENT = 2;
+
+ /** auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL} **/
+ private long interval = DEFAULT_INTERVAL;
+ /** auto scroll direction, default is {@link #RIGHT} **/
+ private int direction = RIGHT;
+ /** whether automatic cycle when auto scroll reaching the last or first item, default is true **/
+ private boolean isCycle = true;
+ /** whether stop auto scroll when touching, default is true **/
+ private boolean stopScrollWhenTouch = true;
+ /** how to process when sliding at the last or first item, default is {@link #SLIDE_BORDER_MODE_NONE} **/
+ private int slideBorderMode = SLIDE_BORDER_MODE_NONE;
+ /** whether animating when auto scroll at the last or first item **/
+ private boolean isBorderAnimation = true;
+ /** scroll factor for auto scroll animation, default is 1.0 **/
+ private double autoScrollFactor = 1.0;
+ /** scroll factor for swipe scroll animation, default is 1.0 **/
+ private double swipeScrollFactor = 1.0;
+
+ private Handler handler;
+ private boolean isAutoScroll = false;
+ private boolean isStopByTouch = false;
+ private float touchX = 0f, downX = 0f;
+ private CustomDurationScroller scroller = null;
+
+ public static final int SCROLL_WHAT = 0;
+
+ public AutoScrollViewPager(Context paramContext) {
+ super(paramContext);
+ init();
+ }
+
+ public AutoScrollViewPager(Context paramContext, AttributeSet paramAttributeSet) {
+ super(paramContext, paramAttributeSet);
+ init();
+ }
+
+ private void init() {
+ handler = new MyHandler(this);
+ setViewPagerScroller();
+ }
+
+ /**
+ * start auto scroll, first scroll delay time is {@link #getInterval()}
+ */
+ public void startAutoScroll() {
+ isAutoScroll = true;
+ sendScrollMessage((long)(interval + scroller.getDuration() / autoScrollFactor * swipeScrollFactor));
+ }
+
+ /**
+ * start auto scroll
+ *
+ * @param delayTimeInMills first scroll delay time
+ */
+ public void startAutoScroll(int delayTimeInMills) {
+ isAutoScroll = true;
+ sendScrollMessage(delayTimeInMills);
+ }
+
+ /**
+ * stop auto scroll
+ */
+ public void stopAutoScroll() {
+ isAutoScroll = false;
+ handler.removeMessages(SCROLL_WHAT);
+ }
+
+ /**
+ * set the factor by which the duration of sliding animation will change while swiping
+ */
+ public void setSwipeScrollDurationFactor(double scrollFactor) {
+ swipeScrollFactor = scrollFactor;
+ }
+
+ /**
+ * set the factor by which the duration of sliding animation will change while auto scrolling
+ */
+ public void setAutoScrollDurationFactor(double scrollFactor) {
+ autoScrollFactor = scrollFactor;
+ }
+
+ private void sendScrollMessage(long delayTimeInMills) {
+ /** remove messages before, keeps one message is running at most **/
+ handler.removeMessages(SCROLL_WHAT);
+ handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
+ }
+
+ /**
+ * set ViewPager scroller to change animation duration when sliding
+ */
+ private void setViewPagerScroller() {
+ try {
+ Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
+ scrollerField.setAccessible(true);
+ Field interpolatorField = ViewPager.class.getDeclaredField("sInterpolator");
+ interpolatorField.setAccessible(true);
+
+ scroller = new CustomDurationScroller(getContext(), (Interpolator)interpolatorField.get(null));
+ scrollerField.set(this, scroller);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * scroll only once
+ */
+ public void scrollOnce() {
+ PagerAdapter adapter = getAdapter();
+ int currentItem = getCurrentItem();
+ int totalCount;
+ if (adapter == null || (totalCount = adapter.getCount()) <= 1) {
+ return;
+ }
+
+ int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
+ if (nextItem < 0) {
+ if (isCycle) {
+ setCurrentItem(totalCount - 1, isBorderAnimation);
+ }
+ } else if (nextItem == totalCount) {
+ if (isCycle) {
+ setCurrentItem(0, isBorderAnimation);
+ }
+ } else {
+ setCurrentItem(nextItem, true);
+ }
+ }
+ float mFirstMotionX;
+ float mFirstMotionY;
+ long mFirstTime;
+
+ /**
+ *
+ * if stopScrollWhenTouch is true
+ * if event is down, stop auto scroll.
+ * if event is up, start auto scroll again.
+ *
+ */
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ int action = MotionEventCompat.getActionMasked(ev);
+
+ if (stopScrollWhenTouch) {
+ if ((action == MotionEvent.ACTION_DOWN) && isAutoScroll) {
+ isStopByTouch = true;
+ stopAutoScroll();
+
+ mFirstMotionX = ev.getX();
+ mFirstMotionY = ev.getY();
+ mFirstTime = 0L;
+ } else if (ev.getAction() == MotionEvent.ACTION_UP && isStopByTouch) {
+ startAutoScroll();
+ }
+ }
+
+ if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT || slideBorderMode == SLIDE_BORDER_MODE_CYCLE) {
+ touchX = ev.getX();
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ downX = touchX;
+ }
+ int currentItem = getCurrentItem();
+ PagerAdapter adapter = getAdapter();
+ int pageCount = adapter == null ? 0 : adapter.getCount();
+ /**
+ * current index is first one and slide to right or current index is last one and slide to left.
+ * if slide border mode is to parent, then requestDisallowInterceptTouchEvent false.
+ * else scroll to last one when current item is first one, scroll to first one when current item is last
+ * one.
+ */
+ if ((currentItem == 0 && downX <= touchX) || (currentItem == pageCount - 1 && downX >= touchX)) {
+ if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT) {
+ getParent().requestDisallowInterceptTouchEvent(false);
+ } else {
+ if (pageCount > 1) {
+ Log.e("dd", pageCount - currentItem - 1+" pageCount");
+ setCurrentItem(pageCount - currentItem - 1, isBorderAnimation);
+ }
+ getParent().requestDisallowInterceptTouchEvent(true);
+ }
+ return super.dispatchTouchEvent(ev);
+ }
+ }
+
+ if(ev.getAction() == MotionEvent.ACTION_MOVE){
+ if(mFirstTime == 0L ){
+ mFirstTime = System.currentTimeMillis();
+ }
+ if( System.currentTimeMillis() - mFirstTime < 500){
+ float absX = Math.abs(ev.getX()-mFirstMotionX);
+ float absY = Math.abs(ev.getY()-mFirstMotionY);
+ if(absY < absX ){
+ getParent().requestDisallowInterceptTouchEvent(true);
+ }else{
+ getParent().requestDisallowInterceptTouchEvent(false);
+ }
+ }
+
+ }
+
+// getParent().requestDisallowInterceptTouchEvent(false);
+
+ return super.dispatchTouchEvent(ev);
+ }
+
+ private static class MyHandler extends Handler {
+
+ private final WeakReference autoScrollViewPager;
+
+ public MyHandler(AutoScrollViewPager autoScrollViewPager) {
+ this.autoScrollViewPager = new WeakReference(autoScrollViewPager);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+
+ switch (msg.what) {
+ case SCROLL_WHAT:
+ AutoScrollViewPager pager = this.autoScrollViewPager.get();
+ if (pager != null) {
+ pager.scroller.setScrollDurationFactor(pager.autoScrollFactor);
+ pager.scrollOnce();
+ pager.scroller.setScrollDurationFactor(pager.swipeScrollFactor);
+ pager.sendScrollMessage(pager.interval + pager.scroller.getDuration());
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * get auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}
+ *
+ * @return the interval
+ */
+ public long getInterval() {
+ return interval;
+ }
+
+ /**
+ * set auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}
+ *
+ * @param interval the interval to set
+ */
+ public void setInterval(long interval) {
+ this.interval = interval;
+ }
+
+ /**
+ * get auto scroll direction
+ *
+ * @return {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT}
+ */
+ public int getDirection() {
+ return (direction == LEFT) ? LEFT : RIGHT;
+ }
+
+ /**
+ * set auto scroll direction
+ *
+ * @param direction {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT}
+ */
+ public void setDirection(int direction) {
+ this.direction = direction;
+ }
+
+ /**
+ * whether automatic cycle when auto scroll reaching the last or first item, default is true
+ *
+ * @return the isCycle
+ */
+ public boolean isCycle() {
+ return isCycle;
+ }
+
+ /**
+ * set whether automatic cycle when auto scroll reaching the last or first item, default is true
+ *
+ * @param isCycle the isCycle to set
+ */
+ public void setCycle(boolean isCycle) {
+ this.isCycle = isCycle;
+ }
+
+ /**
+ * whether stop auto scroll when touching, default is true
+ *
+ * @return the stopScrollWhenTouch
+ */
+ public boolean isStopScrollWhenTouch() {
+ return stopScrollWhenTouch;
+ }
+
+ /**
+ * set whether stop auto scroll when touching, default is true
+ *
+ * @param stopScrollWhenTouch
+ */
+ public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) {
+ this.stopScrollWhenTouch = stopScrollWhenTouch;
+ }
+
+ /**
+ * get how to process when sliding at the last or first item
+ *
+ * @return the slideBorderMode {@link #SLIDE_BORDER_MODE_NONE}, {@link #SLIDE_BORDER_MODE_TO_PARENT},
+ * {@link #SLIDE_BORDER_MODE_CYCLE}, default is {@link #SLIDE_BORDER_MODE_NONE}
+ */
+ public int getSlideBorderMode() {
+ return slideBorderMode;
+ }
+
+ /**
+ * set how to process when sliding at the last or first item
+ *
+ * @param slideBorderMode {@link #SLIDE_BORDER_MODE_NONE}, {@link #SLIDE_BORDER_MODE_TO_PARENT},
+ * {@link #SLIDE_BORDER_MODE_CYCLE}, default is {@link #SLIDE_BORDER_MODE_NONE}
+ */
+ public void setSlideBorderMode(int slideBorderMode) {
+ this.slideBorderMode = slideBorderMode;
+ }
+
+ /**
+ * whether animating when auto scroll at the last or first item, default is true
+ *
+ * @return
+ */
+ public boolean isBorderAnimation() {
+ return isBorderAnimation;
+ }
+
+ /**
+ * set whether animating when auto scroll at the last or first item, default is true
+ *
+ * @param isBorderAnimation
+ */
+ public void setBorderAnimation(boolean isBorderAnimation) {
+ this.isBorderAnimation = isBorderAnimation;
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/widget/CustomDurationScroller.java b/base/src/main/java/com/wlj/base/widget/CustomDurationScroller.java
new file mode 100755
index 0000000..6ffbdda
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/CustomDurationScroller.java
@@ -0,0 +1,47 @@
+package com.wlj.base.widget;
+
+import android.content.Context;
+import android.view.animation.Interpolator;
+import android.widget.Scroller;
+
+/**
+ * CustomDurationScroller
+ *
+ * @author Trinea 2014-3-2
+ */
+public class CustomDurationScroller extends Scroller {
+
+ private double scrollFactor = 1;
+
+ public CustomDurationScroller(Context context) {
+ super(context);
+ }
+
+ public CustomDurationScroller(Context context, Interpolator interpolator) {
+ super(context, interpolator);
+ }
+
+ /**
+ * not exist in android 2.3
+ *
+ * @param context
+ * @param interpolator
+ * @param flywheel
+ */
+ // @SuppressLint("NewApi")
+ // public CustomDurationScroller(Context context, Interpolator interpolator, boolean flywheel){
+ // super(context, interpolator, flywheel);
+ // }
+
+ /**
+ * Set the factor by which the duration will change
+ */
+ public void setScrollDurationFactor(double scrollFactor) {
+ this.scrollFactor = scrollFactor;
+ }
+
+ @Override
+ public void startScroll(int startX, int startY, int dx, int dy, int duration) {
+ super.startScroll(startX, startY, dx, dy, (int)(duration * scrollFactor));
+ }
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/widget/IconfontTextview.java b/base/src/main/java/com/wlj/base/widget/IconfontTextview.java
new file mode 100644
index 0000000..c209f9d
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/IconfontTextview.java
@@ -0,0 +1,68 @@
+package com.wlj.base.widget;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Typeface;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.orhanobut.logger.Logger;
+import com.wlj.base.R;
+import com.wlj.base.util.StringUtils;
+
+/**
+ * IconfontTextview
+ */
+
+public class IconfontTextview extends TextView {
+
+
+ public IconfontTextview(Context context) {
+ this(context,null);
+ }
+
+ public IconfontTextview(Context context, AttributeSet attrs) {
+ this(context, attrs,0);
+ }
+
+ public IconfontTextview(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ init(context, attrs, defStyleAttr,0);
+
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public IconfontTextview(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ init(context, attrs, defStyleAttr,defStyleRes);
+ }
+
+ private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IconfontTextview, defStyleAttr, defStyleRes);
+
+ String iconPath = a.getString(R.styleable.IconfontTextview_assetspath);
+// Logger.d(iconPath+"");
+ initIconfont(iconPath);
+
+ a.recycle();
+ }
+
+ private void initIconfont(String path) {
+
+ if(StringUtils.isEmpty(path) || !path.endsWith(".ttf")){
+ path = "fonts/iconfont.ttf";
+ }
+
+ Typeface t = Typeface.createFromAsset(getContext().getAssets(), path);
+
+ setTypeface(t);
+ }
+
+ public void setIconPath(String iconPath) {
+ initIconfont(iconPath);
+ }
+}
diff --git a/base/src/main/java/com/wlj/base/widget/MyGridView.java b/base/src/main/java/com/wlj/base/widget/MyGridView.java
new file mode 100755
index 0000000..64d3dc7
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/MyGridView.java
@@ -0,0 +1,32 @@
+package com.wlj.base.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.GridView;
+import android.widget.ListView;
+
+public class MyGridView extends GridView {
+
+ public MyGridView(Context context) {
+ super(context);
+ }
+
+ public MyGridView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public MyGridView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * 重写该方法,达到使ListView适应ScrollView的效果
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
+ MeasureSpec.AT_MOST);
+ super.onMeasure(widthMeasureSpec, expandSpec);
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/widget/MyListView.java b/base/src/main/java/com/wlj/base/widget/MyListView.java
new file mode 100755
index 0000000..3b79009
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/MyListView.java
@@ -0,0 +1,30 @@
+package com.wlj.base.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ListView;
+
+public class MyListView extends ListView {
+
+ public MyListView(Context context) {
+ super(context);
+ }
+
+ public MyListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public MyListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * 重写该方法,达到使ListView适应ScrollView的效果
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
+ super.onMeasure(widthMeasureSpec, expandSpec);
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/widget/MyScrollLayout.java b/base/src/main/java/com/wlj/base/widget/MyScrollLayout.java
new file mode 100755
index 0000000..c994c8c
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/MyScrollLayout.java
@@ -0,0 +1,371 @@
+package com.wlj.base.widget;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+
+import com.wlj.base.util.Log;
+
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+import android.widget.ScrollView;
+import android.widget.Scroller;
+
+/**
+ * @ 来源:http://www.open-open.com/lib/view/open1326374891952.html
+ *
+ * @1.默认为滑动模式,要用自动播放调startAutotPay。两种模式的动态切换还有bug
+ * @2.当为手动滑动时,可设置是否可以滑到上一张(setPrescroll)
+ * @3.当为自动播放时,lunliupay可设置重复播放,播放间隔时间waittime
+ *
+ * @author wlj
+ *
+ */
+public class MyScrollLayout extends ViewGroup {
+
+ private static final String TAG = "ScrollLayout";
+ private VelocityTracker mVelocityTracker; // 用于判断甩动手势
+ private static final int SNAP_VELOCITY = 600;
+ private Scroller mScroller; // 滑动控制器
+ private int mCurScreen;
+ private int mDefaultScreen = 0;
+ private float mLastMotionX;
+ /**
+ * 是否可以回滚
+ */
+ private boolean prescroll = true;
+
+ // ---------------------autoplay--------------------------
+ /**
+ * 自动切换间隔时间
+ */
+ private long waittime = 5000;
+
+ /**
+ * 自动切换
+ */
+ private boolean autoplay = false;
+
+ Object lock = new Object();
+ /*
+ * 轮流播放
+ */
+// private boolean lunliupay = true;
+ // ---------------------autoplay--end------------------------
+
+ ScrollView sv01;
+
+ private OnViewChangeListener mOnViewChangeListener;
+
+ public MyScrollLayout(Context context,ScrollView sv01) {
+ super(context);
+ init(context);
+ this.sv01 = sv01;
+ }
+
+ public MyScrollLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public MyScrollLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ private void init(Context context) {
+ mCurScreen = mDefaultScreen;
+ mScroller = new Scroller(context);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ if (changed) {
+ // 把childView 从左往右布局
+ int childLeft = 0;
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View childView = getChildAt(i);
+ if (childView.getVisibility() != View.GONE) {
+ final int childWidth = childView.getMeasuredWidth();
+ childView.layout(childLeft, 0, childLeft + childWidth,
+ childView.getMeasuredHeight());
+ childLeft += childWidth;
+ }
+ }
+ }
+ }
+
+ /**
+ * onMeasure:测量
+ *
+ * 1. widthMeasureSpec和heightMeasureSpec这两个值是android:layout_width="200dp"
+ * android:layout_height="80dp"来定义的, 它由两部分构成,可通过int specModeHeight =
+ * MeasureSpec.getMode(heightMeasureSpec); int specSizeHeight =
+ * MeasureSpec.getSize(heightMeasureSpec)来得到各自的值。
+ * 如果android:layout_width="wrap_content"
+ * 或android:layout_width="fill_parent",哪么得到的specMode为MeasureSpec
+ * .AT_MOST,(如果为精确的值则为MeasureSpec.EXACTLY)?
+ * 另外,specSize要想得到合适的值需要在Androidmanifest.xml中添加
+ * 2.系统默认的onMeasure调用方法是getDefaultSize来实现,有时候在自定义控件的时候多数采用
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ final int width = MeasureSpec.getSize(widthMeasureSpec);
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+
+ //不要下面的两个if,则为FILL_PARENT或者match_parent时 view显示不出来
+ if (widthMode == MeasureSpec.AT_MOST) {
+
+ widthMeasureSpec = MeasureSpec.getSize(widthMeasureSpec);
+ }
+ if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+
+ heightMeasureSpec = MeasureSpec.getSize(heightMeasureSpec);
+ }
+
+ final int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+
+ getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
+ }
+ scrollTo(mCurScreen * width, 0);
+ }
+
+ /**
+ * 速度为0的处理
+ */
+ public void snapToDestination() {
+ final int screenWidth = getWidth();
+ final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;
+ snapToScreen(destScreen);
+ }
+
+ public void snapToScreen(int whichScreen) {
+ // get the valid layout page
+ whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
+ if (getScrollX() != (whichScreen * getWidth())) {
+ final int delta = whichScreen * getWidth() - getScrollX();
+ mScroller.startScroll(getScrollX(), 0, delta, 0,Math.abs(delta) * 2);
+ mCurScreen = whichScreen;
+ invalidate(); // Redraw the layout
+ if (mOnViewChangeListener != null) {
+ mOnViewChangeListener.OnViewChange(mCurScreen);
+ }
+ }
+ }
+
+ private void snapToFirst() {
+ // scrolled to the first
+ int delta = (getChildCount() - 1) * getWidth();
+ mScroller.startScroll(getScrollX(), 0, -delta, 0, Math.abs(delta));
+ mCurScreen = 0;
+ invalidate(); // Redraw the layout
+ if (mOnViewChangeListener != null) {
+ mOnViewChangeListener.OnViewChange(0);
+ }
+ }
+
+
+ @Override
+ public void computeScroll() {
+ if (mScroller.computeScrollOffset()) {
+ scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
+ postInvalidate();
+ }
+ }
+
+ float mFirstMotionX;
+ float mFirstMotionY;
+ long mFirstTime;
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+
+ final int action = event.getAction();
+ final float x = event.getX();
+// final float y = event.getY();
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ stopAutoPay();
+ Log.i("", "onTouchEvent ACTION_DOWN");
+ // VelocityTracker:用于对触摸点的速度跟踪,方便获取触摸点的速度。
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ mVelocityTracker.addMovement(event);
+ }
+ if (!mScroller.isFinished()) {
+ mScroller.abortAnimation();
+ }
+ mLastMotionX = x;
+ getParent().requestDisallowInterceptTouchEvent(false);
+
+ mFirstMotionX = event.getX();
+ mFirstMotionY = event.getY();
+ mFirstTime = 0L;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if(mFirstTime == 0L && sv01 != null ){
+ mFirstTime = System.currentTimeMillis();
+ }
+ if(sv01 != null && System.currentTimeMillis() - mFirstTime < 100){
+ float absX = Math.abs(event.getX()-mFirstMotionX);
+ float absY = Math.abs(event.getY()-mFirstMotionY);
+ if(absY < absX ){
+ getParent().requestDisallowInterceptTouchEvent(true);
+ }else{
+ getParent().requestDisallowInterceptTouchEvent(false);
+ }
+// Log.d("dd", absX +" : "+absY);
+ }else{
+// Log.e(TAG, "ACTION_MOVE");
+ int deltaX = (int) (mLastMotionX - x);
+ if (IsCanMove(deltaX)) {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.addMovement(event);
+ }
+ mLastMotionX = x;
+ scrollBy(deltaX, 0);
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ startAutotPay();
+ // x方向的速度
+ int velocityX = 0;
+ if (mVelocityTracker != null) {
+ mVelocityTracker.addMovement(event);
+ mVelocityTracker.computeCurrentVelocity(1000);
+ velocityX = (int) mVelocityTracker.getXVelocity();
+ }
+ if (velocityX > SNAP_VELOCITY && mCurScreen > 0 && prescroll) {
+ Log.e(TAG, "snap left");
+ snapToScreen(mCurScreen - 1);
+ } else if (velocityX < -SNAP_VELOCITY
+ && mCurScreen < getChildCount() - 1) {
+ Log.e(TAG, "snap right");
+ snapToScreen(mCurScreen + 1);
+ } else {
+ // 速度为0的处理
+ snapToDestination();
+ }
+ Log.e(TAG, "滑动速度: "+velocityX+", SNAP_VELOCITY: "+SNAP_VELOCITY);
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+
+ if(sv01 != null){
+ sv01.requestDisallowInterceptTouchEvent(false);
+ }
+ break;
+ }
+ return true;
+ }
+
+ private boolean IsCanMove(int deltaX) {
+ if (getScrollX() <= 0 && deltaX < 0) {
+ return false;
+ }
+ if (getScrollX() >= (getChildCount() - 1) * getWidth() && deltaX > 0) {
+ return false;
+ }
+ if (deltaX < 0 && !prescroll) {
+ return false;
+ }
+
+ return true;
+ }
+
+ // ------------------------autopay---start--------------------------------------
+ private final int SCROLL_WHAT = 1;
+
+ private void sendScrollMessage(long delayTimeInMills) {
+ /** remove messages before, keeps one message is running at most **/
+ handler.removeMessages(SCROLL_WHAT);
+ handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
+ }
+
+ private Handler handler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+
+ switch (msg.what) {
+ case SCROLL_WHAT:
+ snapToScreen(mCurScreen + 1);
+ sendScrollMessage(waittime);
+ break;
+ }
+ }
+
+ };
+
+ public void startAutotPay() {
+ autoplay = true;
+ sendScrollMessage(waittime);
+ }
+
+ public void stopAutoPay() {
+ autoplay = false;
+ handler.removeMessages(SCROLL_WHAT);
+ }
+
+// public boolean isLunliupay() {
+// return lunliupay;
+// }
+//
+// public void setLunliupay(boolean lunliupay) {
+// this.lunliupay = lunliupay;
+// }
+
+ public long getWaittime() {
+ return waittime;
+ }
+
+ public void setWaittime(long waittime) {
+ this.waittime = waittime;
+ }
+
+ public boolean getAutoplay() {
+ return autoplay;
+ }
+
+ public void setAutoplay(boolean isautoplay) {
+
+ this.autoplay = isautoplay;
+ }
+
+ // ---------------------------------autopay--end--------------------------------
+
+ public void SetOnViewChangeListener(OnViewChangeListener listener) {
+ mOnViewChangeListener = listener;
+ }
+
+ /**
+ * 滑动界面时的其他同步操作
+ *
+ * @author wlj
+ *
+ */
+ public interface OnViewChangeListener {
+ public void OnViewChange(int pos);
+ }
+
+ public boolean getPrescroll() {
+ return prescroll;
+ }
+
+ public void setPrescroll(boolean prescroll) {
+ this.prescroll = prescroll;
+ }
+
+
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/widget/ScllorTabView.java b/base/src/main/java/com/wlj/base/widget/ScllorTabView.java
new file mode 100755
index 0000000..d2496c6
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/ScllorTabView.java
@@ -0,0 +1,74 @@
+package com.wlj.base.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Shader.TileMode;
+import android.util.AttributeSet;
+import android.view.View;
+
+
+public class ScllorTabView extends View {
+
+ private int mTabNum, mCurrentNum;
+ private float mWidth, mTabWidth, mOffset;
+ private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private int mBeginColor;
+ private int mEndColor;
+ LinearGradient gradient;
+
+ public ScllorTabView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setTabNum(int n) {
+ mTabNum = n;
+ }
+
+ public void setCurrentNum(int n) {
+ mCurrentNum = n;
+ mOffset = 0;
+ }
+
+ public void setOffset(int position, float offset) {
+ if (offset == 0) {
+ return;
+ }
+ mCurrentNum = position;
+ mOffset = offset;
+ invalidate();
+ }
+
+ public void setmTabWidth(float mTabWidth) {
+ this.mTabWidth = mTabWidth;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (mTabWidth == 0) {
+ mWidth = getWidth();
+ mTabWidth = mWidth / mTabNum;
+ }
+ //根据位置和偏移量来计算滑动条的位置
+ float left = (mCurrentNum + mOffset) * mTabWidth;
+ final float right = left + mTabWidth;
+ final float top = getPaddingTop();
+ final float bottom = getHeight() - getPaddingBottom();
+
+ // if (gradient == null) {
+ LinearGradient gradient = new LinearGradient(left, getHeight(), right,
+ getHeight(), mBeginColor, mEndColor, TileMode.CLAMP);
+ mPaint.setShader(gradient);
+ // }
+ canvas.drawRect(left, top, right, bottom, mPaint);
+ }
+
+ public void setSelectedColor(int color, int color2) {
+ mBeginColor = color;
+ mEndColor = color2;
+
+ }
+}
+
diff --git a/base/src/main/java/com/wlj/base/widget/StickListView.java b/base/src/main/java/com/wlj/base/widget/StickListView.java
new file mode 100644
index 0000000..e312ba8
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/StickListView.java
@@ -0,0 +1,341 @@
+package com.wlj.base.widget;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import com.wlj.base.util.Log;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+import android.widget.ScrollView;
+/**
+ * 仿qq好友的布局 悬浮(在需要悬浮在view的tag=sticky)
+ * @author wlj
+ *
+ */
+public class StickListView extends ListView {
+
+ private String TAG = "StickListView";
+ private static final String STICKY = "sticky";
+ private View mCurrentStickyView;
+ private GradientDrawable mShadowDrawable;
+ private List mStickyViews;
+ /**
+ * nextStickyView与curStickyView的距离
+ *
+ */
+ private int mStickyViewTopOffset;
+ private int defaultShadowHeight = 5;// 阴影高度
+ private float density;
+ private boolean redirectTouchToStickyView;
+
+ /**
+ * 当点击Sticky的时候,实现某些背景的渐变
+ */
+ private Runnable mInvalidataRunnable = new Runnable() {
+
+ @Override
+ public void run() {
+ if (mCurrentStickyView != null) {
+ int left = mCurrentStickyView.getLeft();
+ int top = 0; //mCurrentStickyView.getTop();
+ int right = mCurrentStickyView.getRight();
+ int bottom = (mCurrentStickyView.getHeight() + mStickyViewTopOffset);
+
+ invalidate(left, top, right, bottom);//直接调用invalidate()方法,请求重新draw(),但只会绘制调用者本身。
+ Log.w(TAG, left+" ,"+ top+" ,"+ right+" ,"+ bottom);
+ }
+
+// postDelayed(this, 150);
+ }
+ };
+
+ private boolean viewloadedcompled;
+
+
+ public StickListView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public StickListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+// int strokeWidth = 5; // 3dp 边框宽度
+// int roundRadius = 15; // 8dp 圆角半径
+// int strokeColor = Color.parseColor("#2E3135");//边框颜色
+ int fillColor = Color.parseColor("#FFFFFF");//内部填充颜色
+//
+ mShadowDrawable = new GradientDrawable();//创建drawable
+ mShadowDrawable.setColor(fillColor);
+// gd.setCornerRadius(roundRadius);
+// gd.setStroke(strokeWidth, strokeColor);
+
+ //渐变色设置方法
+// int colors[] = { 22222222 , 0xAA222222, 0x00222222 };///分别为开始颜色,中间夜色,结束颜色
+// mShadowDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
+
+ mStickyViews = new LinkedList();
+ density = context.getResources().getDisplayMetrics().density;
+ }
+
+ /**
+ * 找到设置tag的View
+ *
+ * @param viewGroup
+ */
+ private void findViewByStickyTag(ViewGroup viewGroup) {
+ int childCount = viewGroup.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = viewGroup.getChildAt(i);
+
+ if (getStringTagForView(child).contains(STICKY) && !mStickyViews.contains(child)) {
+
+ mStickyViews.add(child);
+ }
+
+ if (child instanceof ViewGroup) {
+ findViewByStickyTag((ViewGroup) child);
+ }
+ }
+
+ }
+
+ /**
+ * 界面加载完后,调用的方法
+ */
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if(!viewloadedcompled){
+ findViewByStickyTag(this);
+ }
+ viewloadedcompled = true;
+ }
+
+// @Override
+// protected void onLayout(boolean changed, int l, int t, int r, int b) {
+// onLayout方法是ViewGroup中子View的布局方法,用于放置子View的位置
+//
+// super.onLayout(changed, l, t, r, b);
+//
+// if (changed) {//可以用 getChildAt(0)是因为 ScrollView 只能有一个子布局
+// findViewByStickyTag((ViewGroup) getChildAt(0));
+// showStickyView();
+// }
+// }
+
+ @Override
+ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ super.onScrollChanged(l, t, oldl, oldt);
+
+ if(viewloadedcompled){
+ findViewByStickyTag(this);
+ }
+
+ showStickyView();
+ }
+
+ /**
+ *
+ */
+ private void showStickyView() {
+
+
+ View curStickyView = null;
+ View nextStickyView = null;
+
+ for (View v : mStickyViews) {
+
+ int topOffset = offsetListViewTop(v);
+
+// Rect localVisibleRect = new Rect();
+// v.getLocalVisibleRect(localVisibleRect);
+// int topOffset2 = -localVisibleRect.top;
+// Log.e(TAG, "topOffset="+topOffset+" ,topOffset2="+topOffset2);
+//
+// Rect r = new Rect();
+// boolean b = v.getLocalVisibleRect(r);//获取视图本身可见的坐标区域,坐标以自己的左上角为原点
+// // v.localVisibleRect=true, Rect=Rect(0, 0 - 768, 70) localVisibleRect=true, Rect=Rect(0, 0 - 768, 70)
+//
+// int[] location = new int[2];
+// v.getLocationOnScreen(location);//获取在整个屏幕内的绝对坐标,注意这个值是要从屏幕顶端算起,也就是包括了通知栏的高度。
+// // getLocationOnScreen=0:130 getLocationOnScreen=0:483
+// // v.getLocationOnScreen=0:430 v. getLocationOnScreen=0:595
+//
+// Rect g = new Rect();
+// v.getGlobalVisibleRect(g);//方法的作用是获取视图在屏幕坐标中的可视区域
+// // getGlobalVisibleRect=Rect(0, 130 - 768, 1280) getGlobalVisibleRect=Rect(0, 483 - 768, 1280)
+// // v.getGlobalVisibleRect=Rect(0, 430 - 768, 500) v. getGlobalVisibleRect=Rect(0, 595 - 768, 665)
+//
+// Log.i(TAG, "top="+top); //top=300
+// Log.i(TAG," localVisibleRect=" + b +", Rect=" + r.toString() );
+// Log.i(TAG," getLocationOnScreen="+ location[0]+":"+location[1] );
+// Log.i(TAG," getGlobalVisibleRect="+g.toString());
+// Log.i(TAG," scrollY="+scrollY); // scrollY=0
+
+ if (topOffset <= 0) {
+ if (curStickyView == null
+ || topOffset > offsetListViewTop(curStickyView)// 当前v近于curStickyView,此情况为重顶部出来一个v替换curStickyView
+ ) {
+ curStickyView = v;
+ }
+ } else {
+ if (nextStickyView == null
+ || topOffset < offsetListViewTop(nextStickyView)) {
+ nextStickyView = v;
+ }
+ }
+ }
+
+ if (curStickyView != null) {
+ mStickyViewTopOffset = nextStickyView == null ? 0 : Math.min(
+ 0,
+ offsetListViewTop(nextStickyView)
+ - curStickyView.getHeight());
+ mCurrentStickyView = curStickyView;
+
+ removeCallbacks(mInvalidataRunnable);
+ post(mInvalidataRunnable);
+ } else {
+ mCurrentStickyView = null;
+ removeCallbacks(mInvalidataRunnable);
+ }
+
+ }
+ /**
+ * v到本listview顶部的偏移,负数表示v到了listview顶部的上方。
+ * @param v
+ * @return
+ */
+ private int offsetListViewTop(View v) {
+ int[] locationOnScreen_listview = new int[2];
+ getLocationOnScreen(locationOnScreen_listview);//locationOnScreen_listview[1] =listview到屏幕顶端的距离
+
+ int[] locationOnScreen_view = new int[2];
+ v.getLocationOnScreen(locationOnScreen_view);//locationOnScreen_view[1] =view到屏幕顶端的距离
+
+ int viewTopOffsetScreen = locationOnScreen_view[1];
+ int listviewTopOffsetScreen = locationOnScreen_listview[1];
+
+ int topOffset = viewTopOffsetScreen - listviewTopOffsetScreen;//view到listview 偏移
+ return topOffset;
+ }
+
+// private int getScrollY_(View v) {
+// int offsetListViewTop = offsetListViewTop(v);
+// return Math.abs(offsetListViewTop);
+// }
+ private String getStringTagForView(View v) {
+ Object tag = v.getTag();
+ return String.valueOf(tag);
+ }
+
+ /**
+ * 将sticky画出来
+ */
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+// 绘制VIew本身的内容,通过调用View.onDraw(canvas)函数实现
+// 绘制自己的孩子通过dispatchDraw(canvas)实现
+ /**
+ * View组件的绘制会调用draw(Canvas canvas)方法,draw过程中主要是先画Drawable背景,
+ * 对 drawable调用setBounds()然后是draw(Canvas c)方法.有点注意的是背景drawable的实际大小会影响view组件的大小,
+ * drawable的实际大小通过getIntrinsicWidth()和getIntrinsicHeight()获取,当背景比较大时view组件大小等于背景drawable的大小
+ * 画完背景后,draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法,
+ * dispatchDraw()主要是分发给子组件进行绘制,我们通常定制组件的时候重写的是onDraw()方法。值得注意的是ViewGroup容器组件的绘制,
+ * 当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,
+ * 而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法,
+ * 或者自定制一个Drawable,重写它的draw(Canvas c)和 getIntrinsicWidth(),
+ */
+ super.dispatchDraw(canvas);
+ if (mCurrentStickyView != null) {
+ // 先保存起来
+ canvas.save();
+ // 将坐标原点移动到(0, getScrollY() + mStickyViewTopOffset)
+ canvas.translate(0, 0 + mStickyViewTopOffset);
+
+ if (mShadowDrawable != null) {
+ int left = 0;
+ int top = mCurrentStickyView.getHeight() + mStickyViewTopOffset;
+ int right = mCurrentStickyView.getWidth();
+ int bottom = top + (int) (density * defaultShadowHeight + 0.5f);
+ mShadowDrawable.setBounds(left, top, right, bottom);
+ mShadowDrawable.draw(canvas);
+ }
+
+ canvas.clipRect(0, mStickyViewTopOffset,
+ mCurrentStickyView.getWidth(),
+ mCurrentStickyView.getHeight());
+
+ mCurrentStickyView.draw(canvas);
+
+ // 重置坐标原点参数
+ canvas.restore();
+ }
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ //mCurrentStickyView点击事件分发
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ redirectTouchToStickyView = true;
+ }
+
+ if (redirectTouchToStickyView) {
+ redirectTouchToStickyView = mCurrentStickyView != null;
+
+ if (redirectTouchToStickyView) {
+ redirectTouchToStickyView = ev.getY() <= (mCurrentStickyView.getHeight() + mStickyViewTopOffset)
+ && ev.getX() >= mCurrentStickyView.getLeft()
+ && ev.getX() <= mCurrentStickyView.getRight();
+ }
+ }
+
+ boolean dispatchTouchEvent ;
+ if (redirectTouchToStickyView) {
+
+ dispatchTouchEvent = mCurrentStickyView.dispatchTouchEvent(ev);
+
+ }else{
+
+ dispatchTouchEvent = super.dispatchTouchEvent(ev);
+ }
+
+ return dispatchTouchEvent;
+ }
+
+ private boolean hasNotDoneActionDown = true;
+
+ @SuppressLint("Recycle")
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ hasNotDoneActionDown = false;
+ }
+
+ if (hasNotDoneActionDown) {
+ MotionEvent down = MotionEvent.obtain(ev);
+ down.setAction(MotionEvent.ACTION_DOWN);
+ super.onTouchEvent(down);
+ hasNotDoneActionDown = false;
+ }
+
+ if (ev.getAction() == MotionEvent.ACTION_UP
+ || ev.getAction() == MotionEvent.ACTION_CANCEL) {
+ hasNotDoneActionDown = true;
+ }
+ return super.onTouchEvent(ev);
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/widget/StickScrollView.java b/base/src/main/java/com/wlj/base/widget/StickScrollView.java
new file mode 100755
index 0000000..f0b5dee
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/StickScrollView.java
@@ -0,0 +1,254 @@
+package com.wlj.base.widget;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+/**
+ * 仿qq好友的布局 悬浮(在需要悬浮在view的tag=sticky)
+ * @author wlj
+ *
+ */
+public class StickScrollView extends ScrollView {
+
+ private static final String STICKY = "sticky";
+ private View mCurrentStickyView;
+ private GradientDrawable mShadowDrawable;
+ private List mStickyViews;
+ private int mStickyViewTopOffset;
+ private int defaultShadowHeight = 5;// 阴影高度
+ private float density;
+ private boolean redirectTouchToStickyView;
+
+ /**
+ * 当点击Sticky的时候,实现某些背景的渐变
+ */
+ private Runnable mInvalidataRunnable = new Runnable() {
+
+ @Override
+ public void run() {
+ if (mCurrentStickyView != null) {
+ int left = mCurrentStickyView.getLeft();
+ int top = mCurrentStickyView.getTop();
+ int right = mCurrentStickyView.getRight();
+ int bottom = getScrollY()
+ + (mCurrentStickyView.getHeight() + mStickyViewTopOffset);
+
+ invalidate(left, top, right, bottom);
+ }
+
+ postDelayed(this, 16);
+
+ }
+ };
+
+ public StickScrollView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public StickScrollView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+// int strokeWidth = 5; // 3dp 边框宽度
+// int roundRadius = 15; // 8dp 圆角半径
+// int strokeColor = Color.parseColor("#2E3135");//边框颜色
+ int fillColor = Color.parseColor("#FFFFFF");//内部填充颜色
+//
+ mShadowDrawable = new GradientDrawable();//创建drawable
+ mShadowDrawable.setColor(fillColor);
+// gd.setCornerRadius(roundRadius);
+// gd.setStroke(strokeWidth, strokeColor);
+
+ //渐变色设置方法
+// int colors[] = { 22222222 , 0xAA222222, 0x00222222 };///分别为开始颜色,中间夜色,结束颜色
+// mShadowDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
+
+ mStickyViews = new LinkedList();
+ density = context.getResources().getDisplayMetrics().density;
+ }
+
+ /**
+ * 找到设置tag的View
+ *
+ * @param viewGroup
+ */
+ private void findViewByStickyTag(ViewGroup viewGroup) {
+ int childCount = ((ViewGroup) viewGroup).getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = viewGroup.getChildAt(i);
+
+ if (getStringTagForView(child).contains(STICKY)) {
+ mStickyViews.add(child);
+ }
+
+ if (child instanceof ViewGroup) {
+ findViewByStickyTag((ViewGroup) child);
+ }
+ }
+
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+// onLayout方法是ViewGroup中子View的布局方法,用于放置子View的位置
+
+ super.onLayout(changed, l, t, r, b);
+ if (changed) {//可以用 getChildAt(0)是因为 ScrollView 只能有一个子布局
+ findViewByStickyTag((ViewGroup) getChildAt(0));
+ }
+ showStickyView();
+ }
+
+ @Override
+ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ super.onScrollChanged(l, t, oldl, oldt);
+ showStickyView();
+ }
+
+ /**
+ *
+ */
+ private void showStickyView() {
+ View curStickyView = null;
+ View nextStickyView = null;
+
+ for (View v : mStickyViews) {
+ int topOffset = v.getTop() - getScrollY();
+
+ if (topOffset <= 0) {
+ if (curStickyView == null
+ || topOffset > curStickyView.getTop() - getScrollY()) {
+ curStickyView = v;
+ }
+ } else {
+ if (nextStickyView == null
+ || topOffset < nextStickyView.getTop() - getScrollY()) {
+ nextStickyView = v;
+ }
+ }
+ }
+
+ if (curStickyView != null) {
+ mStickyViewTopOffset = nextStickyView == null ? 0 : Math.min(
+ 0,
+ nextStickyView.getTop() - getScrollY()
+ - curStickyView.getHeight());
+ mCurrentStickyView = curStickyView;
+ post(mInvalidataRunnable);
+ } else {
+ mCurrentStickyView = null;
+ removeCallbacks(mInvalidataRunnable);
+
+ }
+
+ }
+
+ private String getStringTagForView(View v) {
+ Object tag = v.getTag();
+ return String.valueOf(tag);
+ }
+
+ /**
+ * 将sticky画出来
+ */
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+// 绘制VIew本身的内容,通过调用View.onDraw(canvas)函数实现
+// 绘制自己的孩子通过dispatchDraw(canvas)实现
+ /**
+ * View组件的绘制会调用draw(Canvas canvas)方法,draw过程中主要是先画Drawable背景,
+ * 对 drawable调用setBounds()然后是draw(Canvas c)方法.有点注意的是背景drawable的实际大小会影响view组件的大小,
+ * drawable的实际大小通过getIntrinsicWidth()和getIntrinsicHeight()获取,当背景比较大时view组件大小等于背景drawable的大小
+ * 画完背景后,draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法,
+ * dispatchDraw()主要是分发给子组件进行绘制,我们通常定制组件的时候重写的是onDraw()方法。值得注意的是ViewGroup容器组件的绘制,
+ * 当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,
+ * 而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法,
+ * 或者自定制一个Drawable,重写它的draw(Canvas c)和 getIntrinsicWidth(),
+ */
+ super.dispatchDraw(canvas);
+ if (mCurrentStickyView != null) {
+ // 先保存起来
+ canvas.save();
+ // 将坐标原点移动到(0, getScrollY() + mStickyViewTopOffset)
+ canvas.translate(0, getScrollY() + mStickyViewTopOffset);
+
+ if (mShadowDrawable != null) {
+ int left = 0;
+ int top = mCurrentStickyView.getHeight() + mStickyViewTopOffset;
+ int right = mCurrentStickyView.getWidth();
+ int bottom = top + (int) (density * defaultShadowHeight + 0.5f);
+ mShadowDrawable.setBounds(left, top, right, bottom);
+ mShadowDrawable.draw(canvas);
+ }
+
+ canvas.clipRect(0, mStickyViewTopOffset,
+ mCurrentStickyView.getWidth(),
+ mCurrentStickyView.getHeight());
+
+ mCurrentStickyView.draw(canvas);
+
+ // 重置坐标原点参数
+ canvas.restore();
+ }
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ redirectTouchToStickyView = true;
+ }
+
+ if (redirectTouchToStickyView) {
+ redirectTouchToStickyView = mCurrentStickyView != null;
+
+ if (redirectTouchToStickyView) {
+ redirectTouchToStickyView = ev.getY() <= (mCurrentStickyView.getHeight() + mStickyViewTopOffset)
+ && ev.getX() >= mCurrentStickyView.getLeft()
+ && ev.getX() <= mCurrentStickyView.getRight();
+ }
+ }
+
+ if (redirectTouchToStickyView) {
+ ev.offsetLocation(0, -1 * ((getScrollY() + mStickyViewTopOffset) - mCurrentStickyView.getTop()) );
+ }
+ return super.dispatchTouchEvent(ev);
+ }
+
+ private boolean hasNotDoneActionDown = true;
+
+ @SuppressLint("Recycle")
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (redirectTouchToStickyView) {
+ ev.offsetLocation(0,((getScrollY() + mStickyViewTopOffset) - mCurrentStickyView.getTop()));
+ }
+
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ hasNotDoneActionDown = false;
+ }
+
+ if (hasNotDoneActionDown) {
+ MotionEvent down = MotionEvent.obtain(ev);
+ down.setAction(MotionEvent.ACTION_DOWN);
+ super.onTouchEvent(down);
+ hasNotDoneActionDown = false;
+ }
+
+ if (ev.getAction() == MotionEvent.ACTION_UP
+ || ev.getAction() == MotionEvent.ACTION_CANCEL) {
+ hasNotDoneActionDown = true;
+ }
+ return super.onTouchEvent(ev);
+ }
+
+}
diff --git a/base/src/main/java/com/wlj/base/widget/SwitchViewDemoActivity.java b/base/src/main/java/com/wlj/base/widget/SwitchViewDemoActivity.java
new file mode 100755
index 0000000..38aaa6d
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/SwitchViewDemoActivity.java
@@ -0,0 +1,196 @@
+package com.wlj.base.widget;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+
+import com.wlj.base.R;
+import com.wlj.base.util.DpAndPx;
+import com.wlj.base.util.Log;
+import com.wlj.base.widget.MyScrollLayout.OnViewChangeListener;
+
+/**
+ * 滑动切换图片和点。
+ * 1.可以通过addSwitchPage添加切换layout,scrollPoint修改Point和添加layout
+ * 2.可以设置Point的图片selector资源等
+ *
+ * @author wlj
+ * @deprecated 用SwitchViewPagerDemoActivity代替,这个的图片管理没做好
+ */
+public abstract class SwitchViewDemoActivity implements OnViewChangeListener, OnClickListener{
+
+ protected MyScrollLayout mScrollLayout;
+ private ImageView[] mImageViews;
+ private int mViewCount;
+ private int mCurSel;
+ private Context mContext;
+ /**
+ * 圆点的图片资源路径(这里必须是Enabled的selector)
+ */
+ private int pointResId = R.drawable.loading_point_selector ;
+ /**
+ * 圆点的容器
+ */
+ private LinearLayout pointlinearLayout;
+
+ /**
+ * 圆点的容器的 LayoutParams
+ */
+ private RelativeLayout.LayoutParams params;
+
+ private LayoutParams scrollLayoutParams;
+
+// private ScrollView sv01;
+
+ private SwitchViewDemoActivity(Context mContext){
+ this.mContext = mContext;
+ scrollLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
+
+ params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ params.setMargins(0, 0, 0, DpAndPx.dpToPx(mContext, 24));
+ params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);//必须加这个,否则setMargins的24没用
+
+ }
+ /**
+ * 有外层滚动视图
+ * @param mContext
+ * @param sv01
+ */
+ public SwitchViewDemoActivity(Context mContext,ScrollView sv01){
+ this(mContext);
+ mScrollLayout = new MyScrollLayout(mContext,sv01);
+ }
+ float mLastMotionX;
+ float mLastMotionY;
+ long mLastTime;
+ public View createview() {
+ RelativeLayout layout = new RelativeLayout(mContext);
+ pointlinearLayout = new LinearLayout(mContext);
+ addSwitchPage(mScrollLayout);
+
+ layout.addView(mScrollLayout, scrollLayoutParams);
+ scrollPoint(layout);
+ layout.setLayoutParams(scrollLayoutParams);
+
+ return layout;
+ }
+
+ /**
+ * 可以继承重写Point,也可以用layout,往布局里面添加其他布局
+ * @param layout 包裹ScrollLayout和pointlinearLayout的最外层layout
+ */
+ protected void scrollPoint(RelativeLayout layout){
+
+ pointlinearLayout.setLayoutParams(params);
+ pointlinearLayout.setGravity(Gravity.CENTER_HORIZONTAL);
+ pointlinearLayout.setOrientation(LinearLayout.HORIZONTAL);
+
+ mViewCount = mScrollLayout.getChildCount();
+ mImageViews = new ImageView[mViewCount];
+ if(mViewCount <= 0 ){
+ return;
+ }
+ ImageView imageView;
+ for(int i = 0; i < mViewCount; i++){
+ imageView = new ImageView(mContext);
+ imageView.setImageResource(pointResId);
+ int px15 = DpAndPx.dpToPx(mContext, 20);
+ int px5 = DpAndPx.dpToPx(mContext, 5);
+ imageView.setPadding(px5, px5, px5, px15);
+ imageView.setOnClickListener(this);
+ mImageViews[i] = imageView;
+ mImageViews[i].setEnabled(true);//这里必须设置true,否则点击不起
+ mImageViews[i].setOnClickListener(this);
+ mImageViews[i].setTag(i);
+ pointlinearLayout.addView(imageView);
+ }
+ mCurSel = 0;
+ mImageViews[mCurSel].setEnabled(false);
+ mScrollLayout.SetOnViewChangeListener(this);
+
+ layout.addView(pointlinearLayout);
+ }
+
+ private void setCurPoint(int index)
+ {
+ if (index < 0 || index > mViewCount - 1 || mCurSel == index) {
+ return ;
+ }
+ mImageViews[mCurSel].setEnabled(true);
+ mImageViews[index].setEnabled(false);
+ mCurSel = index;
+ }
+
+ @Override
+ public void OnViewChange(int pos) {
+ // TODO Auto-generated method stub
+ setCurPoint(pos);
+ }
+
+ @Override
+ public void onClick(View v) {
+ int pos = (Integer)(v.getTag());
+ mScrollLayout.snapToScreen(pos);
+ }
+
+ public int getPointResId() {
+ return pointResId;
+ }
+
+ public void setPointResId(int pointResId) {
+ this.pointResId = pointResId;
+ }
+
+ public ImageView[] getmImageViews() {
+ return mImageViews;
+ }
+
+ public void setmImageViews(ImageView[] mImageViews) {
+ this.mImageViews = mImageViews;
+ }
+
+ public LinearLayout getPointlinearLayout() {
+ return pointlinearLayout;
+ }
+
+ public void setPointlinearLayout(LinearLayout pointlinearLayout) {
+ this.pointlinearLayout = pointlinearLayout;
+ }
+
+ public RelativeLayout.LayoutParams getParams() {
+ return params;
+ }
+
+ public void setParams(RelativeLayout.LayoutParams params) {
+ this.params = params;
+ }
+
+ public LayoutParams getScrollLayoutParams() {
+ return scrollLayoutParams;
+ }
+
+ public void setScrollLayoutParams(LayoutParams scrollLayoutParams) {
+ this.scrollLayoutParams = scrollLayoutParams;
+ }
+
+ /**
+ * 给滑视图添加页面
+ * @param mScrollLayout
+ */
+ protected abstract void addSwitchPage(MyScrollLayout mScrollLayout);
+
+
+
+}
\ No newline at end of file
diff --git a/base/src/main/java/com/wlj/base/widget/SwitchViewPager.java b/base/src/main/java/com/wlj/base/widget/SwitchViewPager.java
new file mode 100755
index 0000000..1409c35
--- /dev/null
+++ b/base/src/main/java/com/wlj/base/widget/SwitchViewPager.java
@@ -0,0 +1,270 @@
+package com.wlj.base.widget;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import android.content.Context;
+import android.support.v4.view.ViewPager.OnPageChangeListener;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+import com.bumptech.glide.Glide;
+import com.wlj.base.R;
+import com.wlj.base.adapter.ImagePagerAdapter;
+import com.wlj.base.bean.Banner;
+import com.wlj.base.util.DpAndPx;
+import com.wlj.base.util.ListUtils;
+import com.wlj.base.util.img.LoadImage;
+
+/**
+ * @author wlj
+ */
+public class SwitchViewPager implements
+ OnPageChangeListener {
+
+ private AutoScrollViewPager autoScrollViewPager;
+ private ImageView[] mImageViews;
+ private int mViewCount;
+ private int mCurSel;
+ private Context mContext;
+ private List list;
+ /**
+ * 圆点的图片资源路径(这里必须是Enabled的selector)
+ */
+ private int pointResId = R.drawable.loading_point_selector;
+ /**
+ * 圆点的容器
+ */
+ private LinearLayout pointlinearLayout;
+
+ /**
+ * 圆点的容器的 LayoutParams
+ */
+ private RelativeLayout.LayoutParams params;
+
+ private LayoutParams scrollLayoutParams;
+ private final int TUANGOU = 1;
+
+ /**
+ * @param list 图片url的list
+ */
+ public SwitchViewPager(Context mContext, List list) {
+
+
+ this.mContext = mContext;
+ this.list = list;
+ this.mViewCount = ListUtils.getSize(list);
+
+ scrollLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, DpAndPx.dpToPx(mContext, 200));
+// scrollLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+
+ params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ params.setMargins(0, 0, 0, DpAndPx.dpToPx(mContext, 2));
+ params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);// 必须加这个,否则setMargins的24没用
+
+ }
+
+ public View createview() {
+
+ RelativeLayout layout = new RelativeLayout(mContext);
+ if (list.size() <= 0) {
+ layout.setLayoutParams(scrollLayoutParams);
+ return layout;
+ }
+
+ autoScrollViewPager = new AutoScrollViewPager(mContext);
+
+ autoScrollViewPager.setInterval(3000);// 设置自动滚动的间隔时间,单位为毫秒
+ autoScrollViewPager.setSlideBorderMode(AutoScrollViewPager.SLIDE_BORDER_MODE_CYCLE);// 滑动到第一个或最后一个Item的处理方式,支持没有任何操作、轮播以及传递到父View三种模式
+ autoScrollViewPager.setAutoScrollDurationFactor(4);//设置ViewPager滑动动画间隔时间的倍率,达到减慢动画或改变动画速度的效果
+// autoScrollViewPager.setDirection(AutoScrollViewPager.RIGHT); // 设置自动滚动的方向,默认向右
+// viewPager.setCycle(true);// 是否自动循环轮播,默认为true
+// viewPager.setStopScrollWhenTouch(true);// 当手指碰到ViewPager时是否停止自动滚动,默认为true
+// viewPager.setBorderAnimation(true);// 设置循环滚动时滑动到从边缘滚动到下一个是否需要动画,默认为true
+
+ addSwitchPage(autoScrollViewPager);
+
+ layout.addView(autoScrollViewPager, scrollLayoutParams);
+ scrollPoint(layout);
+ layout.setLayoutParams(scrollLayoutParams);
+ //Integer.MAX_VALUE 的中间数 且 为mViewCount倍数的位置
+ autoScrollViewPager.setCurrentItem(Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mViewCount);
+ return layout;
+ }
+
+ /**
+ * 可以继承重写Point,也可以用layout,往布局里面添加其他布局
+ *
+ * @param layout 包裹ScrollLayout和pointlinearLayout的最外层layout
+ */
+ protected void scrollPoint(RelativeLayout layout) {
+
+ pointlinearLayout = new LinearLayout(mContext);
+ pointlinearLayout.setLayoutParams(params);
+ pointlinearLayout.setGravity(Gravity.CENTER_HORIZONTAL);
+ pointlinearLayout.setOrientation(LinearLayout.HORIZONTAL);
+// pointlinearLayout.setBackgroundColor(Color.parseColor("magenta"));
+
+ mImageViews = new ImageView[mViewCount];
+ if (mViewCount <= 0) {
+ return;
+ }
+ ImageView imageView;
+ for (int i = 0; i < mViewCount; i++) {
+ imageView = new ImageView(mContext);
+ imageView.setImageResource(pointResId);
+ int px10 = DpAndPx.dpToPx(mContext, 5);
+ imageView.setPadding(px10, px10, px10, px10);
+ mImageViews[i] = imageView;
+ mImageViews[i].setEnabled(true);// 这里必须设置true,否则点击不起
+ mImageViews[i].setTag(i);
+ pointlinearLayout.addView(imageView);
+ }
+ mCurSel = 0;
+ mImageViews[mCurSel].setEnabled(false);
+ autoScrollViewPager.setOnPageChangeListener(this);
+
+ layout.addView(pointlinearLayout);
+ }
+
+ private void setCurPoint(int index) {
+ if (index < 0 || index > mViewCount - 1 || mCurSel == index) {
+ return;
+ }
+ mImageViews[mCurSel].setEnabled(true);
+ mImageViews[index].setEnabled(false);
+ mCurSel = index;
+ }
+
+ public int getPointResId() {
+ return pointResId;
+ }
+
+ public void setPointResId(int pointResId) {
+ this.pointResId = pointResId;
+ }
+
+ public ImageView[] getmImageViews() {
+ return mImageViews;
+ }
+
+ public void setmImageViews(ImageView[] mImageViews) {
+ this.mImageViews = mImageViews;
+ }
+
+ public AutoScrollViewPager getAutoScrollViewPager() {
+ return autoScrollViewPager;
+ }
+
+// public void setAutoScrollViewPager(AutoScrollViewPager autoScrollViewPager) {
+// this.autoScrollViewPager = autoScrollViewPager;
+// }
+
+ public LinearLayout getPointlinearLayout() {
+ return pointlinearLayout;
+ }
+
+ public void setPointlinearLayout(LinearLayout pointlinearLayout) {
+ this.pointlinearLayout = pointlinearLayout;
+ }
+
+ public RelativeLayout.LayoutParams getParams() {
+ return params;
+ }
+
+ public void setParams(RelativeLayout.LayoutParams params) {
+ this.params = params;
+ }
+
+ public LayoutParams getScrollLayoutParams() {
+ return scrollLayoutParams;
+ }
+
+ public void setScrollLayoutParams(LayoutParams scrollLayoutParams) {
+ this.scrollLayoutParams = scrollLayoutParams;
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ setCurPoint(position % mViewCount);
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int arg0) {
+ }
+
+ /**
+ * 给滑视图添加页面
+ *
+ * @param autoviewPager
+ */
+ protected void addSwitchPage(AutoScrollViewPager autoviewPager) {
+ autoviewPager.setAdapter(new ImagePagerAdapter(list) {
+ @Override
+ public View getPageItemview(T item, View view, ViewGroup container) {
+ if (view == null) {
+ view = new ImageView(mContext);
+ }
+ final ImageView imageView1 = (ImageView) view;
+
+// LoadImage loadImage = LoadImage.getinstall();
+ imageView1.setAdjustViewBounds(true);
+ imageView1.setScaleType(ScaleType.FIT_XY);
+
+ Glide.with(mContext).
+ load(getContentText(item))
+ .placeholder(R.drawable.project_bg)
+ .crossFade()
+ .into(imageView1);
+
+// loadImage.addTask(getContentText(item), imageView1);
+// loadImage.doTask();
+ imageView1.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (onItemPagerViewClickListener != null){
+ onItemPagerViewClickListener.ItemClickListener(imageView1);
+ }
+ }
+ });
+
+ return imageView1;
+ }
+ }.setInfiniteLoop(true));
+ autoviewPager.startAutoScroll();
+ };
+
+ private String getContentText(T item) {
+
+ if(item instanceof Banner){
+ return ((Banner) item).getPicPath();
+ }
+ return item.toString();
+ }
+
+ private PageritemClickListener onItemPagerViewClickListener;
+
+ public void setOnItemPagerViewClickListener(
+ PageritemClickListener onItemPagerViewClickListener) {
+ this.onItemPagerViewClickListener = onItemPagerViewClickListener;
+ }
+
+ public interface PageritemClickListener {
+
+ void ItemClickListener(ImageView imageView1);
+
+ }
+
+}
\ No newline at end of file
diff --git a/base/src/main/res/drawable-hdpi/project_bg.jpg b/base/src/main/res/drawable-hdpi/project_bg.jpg
new file mode 100755
index 0000000..477c837
Binary files /dev/null and b/base/src/main/res/drawable-hdpi/project_bg.jpg differ
diff --git a/base/src/main/res/drawable-xxhdpi/progress_bg_small.png b/base/src/main/res/drawable-xxhdpi/progress_bg_small.png
new file mode 100755
index 0000000..2d8a148
Binary files /dev/null and b/base/src/main/res/drawable-xxhdpi/progress_bg_small.png differ
diff --git a/base/src/main/res/drawable-xxhdpi/progress_go_small.png b/base/src/main/res/drawable-xxhdpi/progress_go_small.png
new file mode 100755
index 0000000..071af57
Binary files /dev/null and b/base/src/main/res/drawable-xxhdpi/progress_go_small.png differ
diff --git a/base/src/main/res/drawable/loading_point_selector.xml b/base/src/main/res/drawable/loading_point_selector.xml
new file mode 100755
index 0000000..064350a
--- /dev/null
+++ b/base/src/main/res/drawable/loading_point_selector.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/base/src/main/res/layout/progressbar.xml b/base/src/main/res/layout/progressbar.xml
new file mode 100755
index 0000000..28ef44e
--- /dev/null
+++ b/base/src/main/res/layout/progressbar.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/base/src/main/res/values/attrs.xml b/base/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..dda45db
--- /dev/null
+++ b/base/src/main/res/values/attrs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/base/src/main/res/values/colors.xml b/base/src/main/res/values/colors.xml
new file mode 100644
index 0000000..2074bcf
--- /dev/null
+++ b/base/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #202020
+ #666666
+ #aaaaaa
+ #ffffff
+
+ @color/black //状态栏颜色 statusBarColor
+
+
\ No newline at end of file
diff --git a/base/src/main/res/values/ids.xml b/base/src/main/res/values/ids.xml
new file mode 100644
index 0000000..511b3ef
--- /dev/null
+++ b/base/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/base/src/main/res/values/strings.xml b/base/src/main/res/values/strings.xml
new file mode 100644
index 0000000..05ffa52
--- /dev/null
+++ b/base/src/main/res/values/strings.xml
@@ -0,0 +1,7 @@
+
+ base
+ 提示
+ 放开刷新
+ 下拉刷新
+ 刷新中
+
diff --git a/base/src/test/java/com/wlj/base/ExampleUnitTest.java b/base/src/test/java/com/wlj/base/ExampleUnitTest.java
new file mode 100644
index 0000000..684e6f6
--- /dev/null
+++ b/base/src/test/java/com/wlj/base/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.wlj.base;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..a277c4f
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.2.2'
+
+ //这里配置 apt 供butterknife使用
+ classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gesturelock/.gitignore b/gesturelock/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/gesturelock/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/gesturelock/build.gradle b/gesturelock/build.gradle
new file mode 100644
index 0000000..0745116
--- /dev/null
+++ b/gesturelock/build.gradle
@@ -0,0 +1,32 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion '23.0.3'
+
+ defaultConfig {
+ minSdkVersion 15
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
+ compile 'com.android.support:appcompat-v7:23.4.0'
+ testCompile 'junit:junit:4.12'
+ compile project(':base')
+}
diff --git a/gesturelock/proguard-rules.pro b/gesturelock/proguard-rules.pro
new file mode 100644
index 0000000..7de1e98
--- /dev/null
+++ b/gesturelock/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/wlj/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/gesturelock/src/androidTest/java/com/wlj/gesturelock/ExampleInstrumentedTest.java b/gesturelock/src/androidTest/java/com/wlj/gesturelock/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..f06ed62
--- /dev/null
+++ b/gesturelock/src/androidTest/java/com/wlj/gesturelock/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.wlj.gesturelock;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("com.wlj.gesturelock.test", appContext.getPackageName());
+ }
+}
diff --git a/gesturelock/src/main/AndroidManifest.xml b/gesturelock/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b51232c
--- /dev/null
+++ b/gesturelock/src/main/AndroidManifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/GestureEditActivity.java b/gesturelock/src/main/java/com/wlj/gesturelock/GestureEditActivity.java
new file mode 100755
index 0000000..8fe89c3
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/GestureEditActivity.java
@@ -0,0 +1,141 @@
+package com.wlj.gesturelock;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.text.Html;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.wlj.gesturelock.widget.GestureContentView;
+import com.wlj.gesturelock.widget.GestureDrawline;
+import com.wlj.gesturelock.widget.LockIndicator;
+
+
+/**
+ *
+ * 手势密码设置界面
+ *
+ */
+public class GestureEditActivity extends Activity implements OnClickListener {
+ /** 手机号码*/
+ public static final String PARAM_PHONE_NUMBER = "PARAM_PHONE_NUMBER";
+ /** 意图 */
+ public static final String PARAM_INTENT_CODE = "PARAM_INTENT_CODE";
+ /** 首次提示绘制手势密码,可以选择跳过 */
+ public static final String PARAM_IS_FIRST_ADVICE = "PARAM_IS_FIRST_ADVICE";
+ private TextView mTextTitle;
+ private TextView mTextCancel;
+ private LockIndicator mLockIndicator;
+ private TextView mTextTip;
+ private FrameLayout mGestureContainer;
+ private GestureContentView mGestureContentView;
+ private TextView mTextReset;
+ private String mParamSetUpcode = null;
+ private String mParamPhoneNumber;
+ private boolean mIsFirstInput = true;
+ private String mFirstPassword = null;
+ private String mConfirmPassword = null;
+ private int mParamIntentCode;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_gesture_edit);
+ setUpViews();
+ setUpListeners();
+ }
+
+ private void setUpViews() {
+ mTextTitle = (TextView) findViewById(R.id.text_title);
+ mTextCancel = (TextView) findViewById(R.id.text_cancel);
+ mTextReset = (TextView) findViewById(R.id.text_reset);
+ mTextReset.setClickable(false);
+ mLockIndicator = (LockIndicator) findViewById(R.id.lock_indicator);
+ mTextTip = (TextView) findViewById(R.id.text_tip);
+ mGestureContainer = (FrameLayout) findViewById(R.id.gesture_container);
+ // 初始化一个显示各个点的viewGroup
+ mGestureContentView = new GestureContentView(this, false, "", new GestureDrawline.GestureCallBack() {
+ @Override
+ public void onGestureCodeInput(String inputCode) {
+ if (!isInputPassValidate(inputCode)) {
+ mTextTip.setText(Html.fromHtml("最少链接4个点, 请重新输入 "));
+ mGestureContentView.clearDrawlineState(0L);
+ return;
+ }
+ if (mIsFirstInput) {
+ mFirstPassword = inputCode;
+ updateCodeList(inputCode);
+ mGestureContentView.clearDrawlineState(0L);
+ mTextReset.setClickable(true);
+ mTextReset.setText(getString(R.string.reset_gesture_code));
+ } else {
+ if (inputCode.equals(mFirstPassword)) {
+ Toast.makeText(GestureEditActivity.this, "设置成功", Toast.LENGTH_SHORT).show();
+ mGestureContentView.clearDrawlineState(0L);
+ GestureEditActivity.this.finish();
+ } else {
+ mTextTip.setText(Html.fromHtml("与上一次绘制不一致,请重新绘制 "));
+ // 左右移动动画
+ Animation shakeAnimation = AnimationUtils.loadAnimation(GestureEditActivity.this, R.anim.shake);
+ mTextTip.startAnimation(shakeAnimation);
+ // 保持绘制的线,1.5秒后清除
+ mGestureContentView.clearDrawlineState(1300L);
+ }
+ }
+ mIsFirstInput = false;
+ }
+
+ @Override
+ public void checkedSuccess() {
+
+ }
+
+ @Override
+ public void checkedFail() {
+
+ }
+ });
+ // 设置手势解锁显示到哪个布局里面
+ mGestureContentView.setParentView(mGestureContainer);
+ updateCodeList("");
+ }
+
+ private void setUpListeners() {
+ mTextCancel.setOnClickListener(this);
+ mTextReset.setOnClickListener(this);
+ }
+
+ private void updateCodeList(String inputCode) {
+ // 更新选择的图案
+ mLockIndicator.setPath(inputCode);
+ }
+
+ @Override
+ public void onClick(View v) {
+ int i = v.getId();
+ if (i == R.id.text_cancel) {
+ this.finish();
+
+ } else if (i == R.id.text_reset) {
+ mIsFirstInput = true;
+ updateCodeList("");
+ mTextTip.setText(getString(R.string.set_gesture_pattern));
+
+ } else {
+ }
+ }
+
+ private boolean isInputPassValidate(String inputPassword) {
+ if (TextUtils.isEmpty(inputPassword) || inputPassword.length() < 4) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/GestureMainActivity.java b/gesturelock/src/main/java/com/wlj/gesturelock/GestureMainActivity.java
new file mode 100755
index 0000000..aaf746a
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/GestureMainActivity.java
@@ -0,0 +1,54 @@
+package com.wlj.gesturelock;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class GestureMainActivity extends Activity implements OnClickListener {
+ private Button mBtnSetLock;
+ private Button mBtnVerifyLock;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main_gesture);
+ setUpView();
+ setUpListener();
+ }
+
+ private void setUpView() {
+ mBtnSetLock = (Button) findViewById(R.id.btn_set_lockpattern);
+ mBtnVerifyLock = (Button) findViewById(R.id.btn_verify_lockpattern);
+ }
+
+ private void setUpListener() {
+ mBtnSetLock.setOnClickListener(this);
+ mBtnVerifyLock.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ int i = v.getId();
+ if (i == R.id.btn_set_lockpattern) {
+ startSetLockPattern();
+
+ } else if (i == R.id.btn_verify_lockpattern) {
+ startVerifyLockPattern();
+
+ } else {
+ }
+ }
+
+ private void startSetLockPattern() {
+ Intent intent = new Intent(GestureMainActivity.this, GestureEditActivity.class);
+ startActivity(intent);
+ }
+
+ private void startVerifyLockPattern() {
+ Intent intent = new Intent(GestureMainActivity.this, GestureVerifyActivity.class);
+ startActivity(intent);
+ }
+}
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/GestureVerifyActivity.java b/gesturelock/src/main/java/com/wlj/gesturelock/GestureVerifyActivity.java
new file mode 100755
index 0000000..8f288cf
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/GestureVerifyActivity.java
@@ -0,0 +1,134 @@
+package com.wlj.gesturelock;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.Html;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.wlj.gesturelock.widget.GestureContentView;
+import com.wlj.gesturelock.widget.GestureDrawline;
+
+/**
+ *
+ * 手势绘制/校验界面
+ *
+ */
+public class GestureVerifyActivity extends Activity implements android.view.View.OnClickListener {
+ /** 手机号码*/
+ public static final String PARAM_PHONE_NUMBER = "PARAM_PHONE_NUMBER";
+ /** 意图 */
+ public static final String PARAM_INTENT_CODE = "PARAM_INTENT_CODE";
+ private RelativeLayout mTopLayout;
+ private TextView mTextTitle;
+ private TextView mTextCancel;
+ private ImageView mImgUserLogo;
+ private TextView mTextPhoneNumber;
+ private TextView mTextTip;
+ private FrameLayout mGestureContainer;
+ private GestureContentView mGestureContentView;
+ private TextView mTextForget;
+ private TextView mTextOther;
+ private String mParamPhoneNumber;
+ private long mExitTime = 0;
+ private int mParamIntentCode;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_gesture_verify);
+ ObtainExtraData();
+ setUpViews();
+ setUpListeners();
+ }
+
+ private void ObtainExtraData() {
+ mParamPhoneNumber = getIntent().getStringExtra(PARAM_PHONE_NUMBER);
+ mParamIntentCode = getIntent().getIntExtra(PARAM_INTENT_CODE, 0);
+ }
+
+ private void setUpViews() {
+ mTopLayout = (RelativeLayout) findViewById(R.id.top_layout);
+ mTextTitle = (TextView) findViewById(R.id.text_title);
+ mTextCancel = (TextView) findViewById(R.id.text_cancel);
+ mImgUserLogo = (ImageView) findViewById(R.id.user_logo);
+ mTextPhoneNumber = (TextView) findViewById(R.id.text_phone_number);
+ mTextTip = (TextView) findViewById(R.id.text_tip);
+ mGestureContainer = (FrameLayout) findViewById(R.id.gesture_container);
+ mTextForget = (TextView) findViewById(R.id.text_forget_gesture);
+ mTextOther = (TextView) findViewById(R.id.text_other_account);
+
+
+ // 初始化一个显示各个点的viewGroup
+ mGestureContentView = new GestureContentView(this, true, "1235789",
+ new GestureDrawline.GestureCallBack() {
+
+ @Override
+ public void onGestureCodeInput(String inputCode) {
+
+ }
+
+ @Override
+ public void checkedSuccess() {
+ mGestureContentView.clearDrawlineState(0L);
+ Toast.makeText(GestureVerifyActivity.this, "密码正确", Toast.LENGTH_SHORT).show();
+ GestureVerifyActivity.this.finish();
+ }
+
+ @Override
+ public void checkedFail() {
+ mGestureContentView.clearDrawlineState(1300L);
+ mTextTip.setVisibility(View.VISIBLE);
+ mTextTip.setText(Html
+ .fromHtml("密码错误 "));
+ // 左右移动动画
+ Animation shakeAnimation = AnimationUtils.loadAnimation(GestureVerifyActivity.this, R.anim.shake);
+ mTextTip.startAnimation(shakeAnimation);
+ }
+ });
+ // 设置手势解锁显示到哪个布局里面
+ mGestureContentView.setParentView(mGestureContainer);
+ }
+
+ private void setUpListeners() {
+ mTextCancel.setOnClickListener(this);
+ mTextForget.setOnClickListener(this);
+ mTextOther.setOnClickListener(this);
+ }
+
+ private String getProtectedMobile(String phoneNumber) {
+ if (TextUtils.isEmpty(phoneNumber) || phoneNumber.length() < 11) {
+ return "";
+ }
+ StringBuilder builder = new StringBuilder();
+ builder.append(phoneNumber.subSequence(0,3));
+ builder.append("****");
+ builder.append(phoneNumber.subSequence(7,11));
+ return builder.toString();
+ }
+
+
+
+ @Override
+ public void onClick(View v) {
+ int i = v.getId();
+ if (i == R.id.text_cancel) {
+ this.finish();
+
+ } else {
+ }
+ }
+
+}
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/common/AppUtil.java b/gesturelock/src/main/java/com/wlj/gesturelock/common/AppUtil.java
new file mode 100755
index 0000000..7668eac
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/common/AppUtil.java
@@ -0,0 +1,29 @@
+/**
+ *
+ */
+package com.wlj.gesturelock.common;
+
+import java.util.List;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.util.Log;
+import android.view.WindowManager;
+
+public class AppUtil {
+
+ /**
+ * 获取屏幕分辨率
+ * @param context
+ * @return
+ */
+ public static int[] getScreenDispaly(Context context) {
+ WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ int width = windowManager.getDefaultDisplay().getWidth();// 手机屏幕的宽度
+ int height = windowManager.getDefaultDisplay().getHeight();// 手机屏幕的高度
+ int result[] = { width, height };
+ return result;
+ }
+
+}
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/common/Constants.java b/gesturelock/src/main/java/com/wlj/gesturelock/common/Constants.java
new file mode 100755
index 0000000..c1da2cf
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/common/Constants.java
@@ -0,0 +1,11 @@
+package com.wlj.gesturelock.common;
+public class Constants {
+
+ //*/ 手势密码点的状态
+ public static final int POINT_STATE_NORMAL = 0; // 正常状态
+
+ public static final int POINT_STATE_SELECTED = 1; // 按下状态
+
+ public static final int POINT_STATE_WRONG = 2; // 错误状态
+ //*/
+}
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/entity/GesturePoint.java b/gesturelock/src/main/java/com/wlj/gesturelock/entity/GesturePoint.java
new file mode 100755
index 0000000..debe9ac
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/entity/GesturePoint.java
@@ -0,0 +1,192 @@
+package com.wlj.gesturelock.entity;
+
+import android.widget.ImageView;
+
+import com.wlj.gesturelock.R;
+import com.wlj.gesturelock.common.Constants;
+
+public class GesturePoint {
+ /**
+ * 左边x的值
+ */
+ private int leftX;
+ /**
+ * 右边x的值
+ */
+ private int rightX;
+ /**
+ * 上边y的值
+ */
+ private int topY;
+ /**
+ * 下边y的值
+ */
+ private int bottomY;
+ /**
+ * 这个点对应的ImageView控件
+ */
+ private ImageView image;
+
+ /**
+ * 中心x值
+ */
+ private int centerX;
+
+ /**
+ * 中心y值
+ */
+ private int centerY;
+
+ /**
+ * 状态值
+ */
+ private int pointState;
+
+ /**
+ * 代表这个Point对象代表的数字,从1开始(直接感觉从1开始)
+ */
+ private int num;
+
+ public GesturePoint(int leftX, int rightX, int topY, int bottomY,
+ ImageView image, int num) {
+ super();
+ this.leftX = leftX;
+ this.rightX = rightX;
+ this.topY = topY;
+ this.bottomY = bottomY;
+ this.image = image;
+
+ this.centerX = (leftX + rightX) / 2;
+ this.centerY = (topY + bottomY) / 2;
+
+ this.num = num;
+ }
+
+ public int getLeftX() {
+ return leftX;
+ }
+
+ public void setLeftX(int leftX) {
+ this.leftX = leftX;
+ }
+
+ public int getRightX() {
+ return rightX;
+ }
+
+ public void setRightX(int rightX) {
+ this.rightX = rightX;
+ }
+
+ public int getTopY() {
+ return topY;
+ }
+
+ public void setTopY(int topY) {
+ this.topY = topY;
+ }
+
+ public int getBottomY() {
+ return bottomY;
+ }
+
+ public void setBottomY(int bottomY) {
+ this.bottomY = bottomY;
+ }
+
+ public ImageView getImage() {
+ return image;
+ }
+
+ public void setImage(ImageView image) {
+ this.image = image;
+ }
+
+ public int getCenterX() {
+ return centerX;
+ }
+
+ public void setCenterX(int centerX) {
+ this.centerX = centerX;
+ }
+
+ public int getCenterY() {
+ return centerY;
+ }
+
+ public void setCenterY(int centerY) {
+ this.centerY = centerY;
+ }
+
+ public int getPointState() {
+ return pointState;
+ }
+
+ public void setPointState(int state) {
+ pointState = state;
+ switch (state) {
+ case Constants.POINT_STATE_NORMAL:
+ this.image.setBackgroundResource(R.drawable.gesture_node_normal);
+ break;
+ case Constants.POINT_STATE_SELECTED:
+ this.image.setBackgroundResource(R.drawable.gesture_node_pressed);
+ break;
+ case Constants.POINT_STATE_WRONG:
+ this.image.setBackgroundResource(R.drawable.gesture_node_wrong);
+ break;
+ default:
+ break;
+ }
+ }
+
+ public int getNum() {
+ return num;
+ }
+
+ public void setNum(int num) {
+ this.num = num;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + bottomY;
+ result = prime * result + ((image == null) ? 0 : image.hashCode());
+ result = prime * result + leftX;
+ result = prime * result + rightX;
+ result = prime * result + topY;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ GesturePoint other = (GesturePoint) obj;
+ if (bottomY != other.bottomY)
+ return false;
+ if (image == null) {
+ if (other.image != null)
+ return false;
+ } else if (!image.equals(other.image))
+ return false;
+ if (leftX != other.leftX)
+ return false;
+ if (rightX != other.rightX)
+ return false;
+ if (topY != other.topY)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Point [leftX=" + leftX + ", rightX=" + rightX + ", topY="
+ + topY + ", bottomY=" + bottomY + "]";
+ }
+}
\ No newline at end of file
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/widget/GestureContentView.java b/gesturelock/src/main/java/com/wlj/gesturelock/widget/GestureContentView.java
new file mode 100755
index 0000000..5665d9e
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/widget/GestureContentView.java
@@ -0,0 +1,119 @@
+package com.wlj.gesturelock.widget;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.wlj.gesturelock.R;
+import com.wlj.gesturelock.common.AppUtil;
+import com.wlj.gesturelock.entity.GesturePoint;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 手势密码容器类
+ */
+public class GestureContentView extends ViewGroup {
+
+ private int baseNum = 6;
+
+ private int[] screenDispaly;
+
+ /**
+ * 每个点区域的宽度
+ */
+ private int blockWidth;
+ /**
+ * 声明一个集合用来封装坐标集合
+ */
+ private List list;
+ private Context context;
+ private boolean isVerify;
+ private GestureDrawline gestureDrawline;
+
+ /**
+ * 包含9个ImageView的容器,初始化
+ *
+ * @param context
+ * @param isVerify 是否为校验手势密码
+ * @param passWord 用户传入密码
+ * @param callBack 手势绘制完毕的回调
+ */
+ public GestureContentView(Context context, boolean isVerify, String passWord, GestureDrawline.GestureCallBack callBack) {
+ super(context);
+ screenDispaly = AppUtil.getScreenDispaly(context);
+ blockWidth = screenDispaly[0] / 3;
+ this.list = new ArrayList();
+ this.context = context;
+ this.isVerify = isVerify;
+ // 添加9个图标
+ addChild();
+ // 初始化一个可以画线的view
+ gestureDrawline = new GestureDrawline(context, list, isVerify, passWord, callBack);
+ }
+
+ private void addChild() {
+ for (int i = 0; i < 9; i++) {
+ ImageView image = new ImageView(context);
+ image.setBackgroundResource(R.drawable.gesture_node_normal);
+ this.addView(image);
+ invalidate();
+ // 第几行
+ int row = i / 3;
+ // 第几列
+ int col = i % 3;
+ // 定义点的每个属性
+ int leftX = col * blockWidth + blockWidth / baseNum;
+ int topY = row * blockWidth + blockWidth / baseNum;
+ int rightX = col * blockWidth + blockWidth - blockWidth / baseNum;
+ int bottomY = row * blockWidth + blockWidth - blockWidth / baseNum;
+ GesturePoint p = new GesturePoint(leftX, rightX, topY, bottomY, image, i + 1);
+ this.list.add(p);
+ }
+ }
+
+ public void setParentView(ViewGroup parent) {
+ // 得到屏幕的宽度
+ int width = screenDispaly[0];
+ LayoutParams layoutParams = new LayoutParams(width, width);
+ this.setLayoutParams(layoutParams);
+ gestureDrawline.setLayoutParams(layoutParams);
+ parent.addView(gestureDrawline);
+ parent.addView(this);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ for (int i = 0; i < getChildCount(); i++) {
+ //第几行
+ int row = i / 3;
+ //第几列
+ int col = i % 3;
+ View v = getChildAt(i);
+ v.layout(col * blockWidth + blockWidth / baseNum, row * blockWidth + blockWidth / baseNum,
+ col * blockWidth + blockWidth - blockWidth / baseNum, row * blockWidth + blockWidth - blockWidth / baseNum);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ // 遍历设置每个子view的大小
+ for (int i = 0; i < getChildCount(); i++) {
+ View v = getChildAt(i);
+ v.measure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ /**
+ * 保留路径delayTime时间长
+ *
+ * @param delayTime
+ */
+ public void clearDrawlineState(long delayTime) {
+ gestureDrawline.clearDrawlineState(delayTime);
+ }
+
+}
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/widget/GestureDrawline.java b/gesturelock/src/main/java/com/wlj/gesturelock/widget/GestureDrawline.java
new file mode 100755
index 0000000..b0316a9
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/widget/GestureDrawline.java
@@ -0,0 +1,336 @@
+package com.wlj.gesturelock.widget;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.PorterDuff;
+import android.os.Handler;
+import android.util.Pair;
+import android.view.MotionEvent;
+import android.view.View;
+
+
+import com.wlj.gesturelock.common.AppUtil;
+import com.wlj.gesturelock.common.Constants;
+import com.wlj.gesturelock.entity.GesturePoint;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 手势密码路径绘制
+ */
+public class GestureDrawline extends View {
+ private int mov_x;// 声明起点坐标
+ private int mov_y;
+ private Paint paint;// 声明画笔
+ private Canvas canvas;// 画布
+ private Bitmap bitmap;// 位图
+ private List list;// 装有各个view坐标的集合
+ private List> lineList;// 记录画过的线
+ private Map autoCheckPointMap;// 自动选中的情况点
+ private boolean isDrawEnable = true; // 是否允许绘制
+
+ /**
+ * 屏幕的宽度和高度
+ */
+ private int[] screenDispaly;
+
+ /**
+ * 手指当前在哪个Point内
+ */
+ private GesturePoint currentPoint;
+ /**
+ * 用户绘图的回调
+ */
+ private GestureCallBack callBack;
+
+ /**
+ * 用户当前绘制的图形密码
+ */
+ private StringBuilder passWordSb;
+
+ /**
+ * 是否为校验
+ */
+ private boolean isVerify;
+
+ /**
+ * 用户传入的passWord
+ */
+ private String passWord;
+
+ public GestureDrawline(Context context, List list, boolean isVerify,
+ String passWord, GestureCallBack callBack) {
+ super(context);
+ screenDispaly = AppUtil.getScreenDispaly(context);
+ paint = new Paint(Paint.DITHER_FLAG);// 创建一个画笔
+ bitmap = Bitmap.createBitmap(screenDispaly[0], screenDispaly[0], Bitmap.Config.ARGB_8888); // 设置位图的宽高
+ canvas = new Canvas();
+ canvas.setBitmap(bitmap);
+ paint.setStyle(Style.STROKE);// 设置非填充
+ paint.setStrokeWidth(10);// 笔宽5像素
+ paint.setColor(Color.rgb(245, 142, 33));// 设置默认连线颜色
+ paint.setAntiAlias(true);// 不显示锯齿
+
+ this.list = list;
+ this.lineList = new ArrayList>();
+
+ initAutoCheckPointMap();
+ this.callBack = callBack;
+
+ // 初始化密码缓存
+ this.isVerify = isVerify;
+ this.passWordSb = new StringBuilder();
+ this.passWord = passWord;
+ }
+
+ private void initAutoCheckPointMap() {
+ autoCheckPointMap = new HashMap();
+ autoCheckPointMap.put("1,3", getGesturePointByNum(2));
+ autoCheckPointMap.put("1,7", getGesturePointByNum(4));
+ autoCheckPointMap.put("1,9", getGesturePointByNum(5));
+ autoCheckPointMap.put("2,8", getGesturePointByNum(5));
+ autoCheckPointMap.put("3,7", getGesturePointByNum(5));
+ autoCheckPointMap.put("3,9", getGesturePointByNum(6));
+ autoCheckPointMap.put("4,6", getGesturePointByNum(5));
+ autoCheckPointMap.put("7,9", getGesturePointByNum(8));
+ }
+
+ private GesturePoint getGesturePointByNum(int num) {
+ for (GesturePoint point : list) {
+ if (point.getNum() == num) {
+ return point;
+ }
+ }
+ return null;
+ }
+
+ // 画位图
+ @Override
+ protected void onDraw(Canvas canvas) {
+ // super.onDraw(canvas);
+ canvas.drawBitmap(bitmap, 0, 0, null);
+ }
+
+ // 触摸事件
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (isDrawEnable == false) {
+ // 当期不允许绘制
+ return true;
+ }
+ paint.setColor(Color.rgb(245, 142, 33));// 设置默认连线颜色
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mov_x = (int) event.getX();
+ mov_y = (int) event.getY();
+ // 判断当前点击的位置是处于哪个点之内
+ currentPoint = getPointAt(mov_x, mov_y);
+ if (currentPoint != null) {
+ currentPoint.setPointState(Constants.POINT_STATE_SELECTED);
+ passWordSb.append(currentPoint.getNum());
+ }
+ // canvas.drawPoint(mov_x, mov_y, paint);// 画点
+ invalidate();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ clearScreenAndDrawList();
+
+ // 得到当前移动位置是处于哪个点内
+ GesturePoint pointAt = getPointAt((int) event.getX(), (int) event.getY());
+ // 代表当前用户手指处于点与点之前
+ if (currentPoint == null && pointAt == null) {
+ return true;
+ } else {// 代表用户的手指移动到了点上
+ if (currentPoint == null) {// 先判断当前的point是不是为null
+ // 如果为空,那么把手指移动到的点赋值给currentPoint
+ currentPoint = pointAt;
+ // 把currentPoint这个点设置选中为true;
+ currentPoint.setPointState(Constants.POINT_STATE_SELECTED);
+ passWordSb.append(currentPoint.getNum());
+ }
+ }
+ if (pointAt == null || currentPoint.equals(pointAt) || Constants.POINT_STATE_SELECTED == pointAt.getPointState()) {
+ // 点击移动区域不在圆的区域,或者当前点击的点与当前移动到的点的位置相同,或者当前点击的点处于选中状态
+ // 那么以当前的点中心为起点,以手指移动位置为终点画线
+ canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), event.getX(), event.getY(), paint);// 画线
+ } else {
+ // 如果当前点击的点与当前移动到的点的位置不同
+ // 那么以前前点的中心为起点,以手移动到的点的位置画线
+ canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), pointAt.getCenterX(), pointAt.getCenterY(), paint);// 画线
+ pointAt.setPointState(Constants.POINT_STATE_SELECTED);
+
+ // 判断是否中间点需要选中
+ GesturePoint betweenPoint = getBetweenCheckPoint(currentPoint, pointAt);
+ if (betweenPoint != null && Constants.POINT_STATE_SELECTED != betweenPoint.getPointState()) {
+ // 存在中间点并且没有被选中
+ Pair pair1 = new Pair(currentPoint, betweenPoint);
+ lineList.add(pair1);
+ passWordSb.append(betweenPoint.getNum());
+ Pair pair2 = new Pair(betweenPoint, pointAt);
+ lineList.add(pair2);
+ passWordSb.append(pointAt.getNum());
+ // 设置中间点选中
+ betweenPoint.setPointState(Constants.POINT_STATE_SELECTED);
+ // 赋值当前的point;
+ currentPoint = pointAt;
+ } else {
+ Pair pair = new Pair(currentPoint, pointAt);
+ lineList.add(pair);
+ passWordSb.append(pointAt.getNum());
+ // 赋值当前的point;
+ currentPoint = pointAt;
+ }
+ }
+ invalidate();
+ break;
+ case MotionEvent.ACTION_UP:// 当手指抬起的时候
+ if (isVerify) {
+ // 手势密码校验
+ // 清掉屏幕上所有的线,只画上集合里面保存的线
+ if (passWord.equals(passWordSb.toString())) {
+ // 代表用户绘制的密码手势与传入的密码相同
+ callBack.checkedSuccess();
+ } else {
+ // 用户绘制的密码与传入的密码不同。
+ callBack.checkedFail();
+ }
+ } else {
+ callBack.onGestureCodeInput(passWordSb.toString());
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * 指定时间去清除绘制的状态
+ *
+ * @param delayTime 延迟执行时间
+ */
+ public void clearDrawlineState(long delayTime) {
+ if (delayTime > 0) {
+ // 绘制红色提示路线
+ isDrawEnable = false;
+ drawErrorPathTip();
+ }
+ new Handler().postDelayed(new clearStateRunnable(), delayTime);
+ }
+
+ /**
+ * 清除绘制状态的线程
+ */
+ final class clearStateRunnable implements Runnable {
+ public void run() {
+ // 重置passWordSb
+ passWordSb = new StringBuilder();
+ // 清空保存点的集合
+ lineList.clear();
+ // 重新绘制界面
+ clearScreenAndDrawList();
+ for (GesturePoint p : list) {
+ p.setPointState(Constants.POINT_STATE_NORMAL);
+ }
+ invalidate();
+ isDrawEnable = true;
+ }
+ }
+
+ /**
+ * 通过点的位置去集合里面查找这个点是包含在哪个Point里面的
+ *
+ * @param x
+ * @param y
+ * @return 如果没有找到,则返回null,代表用户当前移动的地方属于点与点之间
+ */
+ private GesturePoint getPointAt(int x, int y) {
+
+ for (GesturePoint point : list) {
+ // 先判断x
+ int leftX = point.getLeftX();
+ int rightX = point.getRightX();
+ if (!(x >= leftX && x < rightX)) {
+ // 如果为假,则跳到下一个对比
+ continue;
+ }
+
+ int topY = point.getTopY();
+ int bottomY = point.getBottomY();
+ if (!(y >= topY && y < bottomY)) {
+ // 如果为假,则跳到下一个对比
+ continue;
+ }
+
+ // 如果执行到这,那么说明当前点击的点的位置在遍历到点的位置这个地方
+ return point;
+ }
+
+ return null;
+ }
+
+ private GesturePoint getBetweenCheckPoint(GesturePoint pointStart, GesturePoint pointEnd) {
+ int startNum = pointStart.getNum();
+ int endNum = pointEnd.getNum();
+ String key = null;
+ if (startNum < endNum) {
+ key = startNum + "," + endNum;
+ } else {
+ key = endNum + "," + startNum;
+ }
+ return autoCheckPointMap.get(key);
+ }
+
+ /**
+ * 清掉屏幕上所有的线,然后画出集合里面的线
+ */
+ private void clearScreenAndDrawList() {
+ canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ for (Pair pair : lineList) {
+ canvas.drawLine(pair.first.getCenterX(), pair.first.getCenterY(),
+ pair.second.getCenterX(), pair.second.getCenterY(), paint);// 画线
+ }
+ }
+
+ /**
+ * 校验错误/两次绘制不一致提示
+ */
+ private void drawErrorPathTip() {
+ canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ paint.setColor(Color.rgb(154, 7, 21));// 设置默认线路颜色
+ for (Pair pair : lineList) {
+ pair.first.setPointState(Constants.POINT_STATE_WRONG);
+ pair.second.setPointState(Constants.POINT_STATE_WRONG);
+ canvas.drawLine(pair.first.getCenterX(), pair.first.getCenterY(),
+ pair.second.getCenterX(), pair.second.getCenterY(), paint);// 画线
+ }
+ invalidate();
+ }
+
+
+ public interface GestureCallBack {
+
+ /**
+ * 用户设置/输入了手势密码
+ */
+ public abstract void onGestureCodeInput(String inputCode);
+
+ /**
+ * 代表用户绘制的密码与传入的密码相同
+ */
+ public abstract void checkedSuccess();
+
+ /**
+ * 代表用户绘制的密码与传入的密码不相同
+ */
+ public abstract void checkedFail();
+ }
+
+}
diff --git a/gesturelock/src/main/java/com/wlj/gesturelock/widget/LockIndicator.java b/gesturelock/src/main/java/com/wlj/gesturelock/widget/LockIndicator.java
new file mode 100755
index 0000000..8396633
--- /dev/null
+++ b/gesturelock/src/main/java/com/wlj/gesturelock/widget/LockIndicator.java
@@ -0,0 +1,102 @@
+package com.wlj.gesturelock.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.wlj.gesturelock.R;
+
+
+/**
+ *
+ * 手势密码图案提示
+ *
+ */
+public class LockIndicator extends View {
+ private int numRow = 3; // 行
+ private int numColum = 3; // 列
+ private int patternWidth = 40;
+ private int patternHeight = 40;
+ private int f = 5;
+ private int g = 5;
+ private int strokeWidth = 3;
+ private Paint paint = null;
+ private Drawable patternNoraml = null;
+ private Drawable patternPressed = null;
+ private String lockPassStr; // 手势密码
+
+ public LockIndicator(Context paramContext) {
+ super(paramContext);
+ }
+
+ public LockIndicator(Context paramContext, AttributeSet paramAttributeSet) {
+ super(paramContext, paramAttributeSet, 0);
+ paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setStyle(Paint.Style.STROKE);
+ patternNoraml = getResources().getDrawable(R.drawable.lock_pattern_node_normal);
+ patternPressed = getResources().getDrawable(R.drawable.lock_pattern_node_pressed);
+ if (patternPressed != null) {
+ patternWidth = patternPressed.getIntrinsicWidth();
+ patternHeight = patternPressed.getIntrinsicHeight();
+ this.f = (patternWidth / 4);
+ this.g = (patternHeight / 4);
+ patternPressed.setBounds(0, 0, patternWidth, patternHeight);
+ patternNoraml.setBounds(0, 0, patternWidth, patternHeight);
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if ((patternPressed == null) || (patternNoraml == null)) {
+ return;
+ }
+ // 绘制3*3的图标
+ for (int i = 0; i < numRow; i++) {
+ for (int j = 0; j < numColum; j++) {
+ paint.setColor(Color.parseColor("#565656"));
+ int i1 = j * patternHeight + j * this.g;
+ int i2 = i * patternWidth + i * this.f;
+ canvas.save();
+ canvas.translate(i1, i2);
+ String curNum = String.valueOf(numColum * i + (j + 1));
+ if (!TextUtils.isEmpty(lockPassStr)) {
+ if (lockPassStr.indexOf(curNum) == -1) {
+ // 未选中
+ patternNoraml.draw(canvas);
+ } else {
+ // 被选中
+ patternPressed.draw(canvas);
+ }
+ } else {
+ // 重置状态
+ patternNoraml.draw(canvas);
+ }
+ canvas.restore();
+ }
+ }
+ }
+
+ @Override
+ protected void onMeasure(int paramInt1, int paramInt2) {
+ if (patternPressed != null)
+ setMeasuredDimension(numColum * patternHeight + this.g
+ * (-1 + numColum), numRow * patternWidth + this.f
+ * (-1 + numRow));
+ }
+
+ /**
+ * 请求重新绘制
+ * @param paramString 手势密码字符序列
+ */
+ public void setPath(String paramString) {
+ lockPassStr = paramString;
+ invalidate();
+ }
+}
\ No newline at end of file
diff --git a/gesturelock/src/main/res/anim/shake.xml b/gesturelock/src/main/res/anim/shake.xml
new file mode 100755
index 0000000..8f3d8b4
--- /dev/null
+++ b/gesturelock/src/main/res/anim/shake.xml
@@ -0,0 +1,8 @@
+
+
diff --git a/gesturelock/src/main/res/color/gesture_cancel_text_color.xml b/gesturelock/src/main/res/color/gesture_cancel_text_color.xml
new file mode 100755
index 0000000..7304cda
--- /dev/null
+++ b/gesturelock/src/main/res/color/gesture_cancel_text_color.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/gesturelock/src/main/res/drawable-hdpi/gesture_node_normal.png b/gesturelock/src/main/res/drawable-hdpi/gesture_node_normal.png
new file mode 100755
index 0000000..bce7e95
Binary files /dev/null and b/gesturelock/src/main/res/drawable-hdpi/gesture_node_normal.png differ
diff --git a/gesturelock/src/main/res/drawable-hdpi/gesture_node_pressed.png b/gesturelock/src/main/res/drawable-hdpi/gesture_node_pressed.png
new file mode 100755
index 0000000..588a427
Binary files /dev/null and b/gesturelock/src/main/res/drawable-hdpi/gesture_node_pressed.png differ
diff --git a/gesturelock/src/main/res/drawable-hdpi/gesture_node_wrong.png b/gesturelock/src/main/res/drawable-hdpi/gesture_node_wrong.png
new file mode 100755
index 0000000..1f23910
Binary files /dev/null and b/gesturelock/src/main/res/drawable-hdpi/gesture_node_wrong.png differ
diff --git a/gesturelock/src/main/res/drawable-hdpi/lock_pattern_node_normal.png b/gesturelock/src/main/res/drawable-hdpi/lock_pattern_node_normal.png
new file mode 100755
index 0000000..9f31973
Binary files /dev/null and b/gesturelock/src/main/res/drawable-hdpi/lock_pattern_node_normal.png differ
diff --git a/gesturelock/src/main/res/drawable-hdpi/lock_pattern_node_pressed.png b/gesturelock/src/main/res/drawable-hdpi/lock_pattern_node_pressed.png
new file mode 100755
index 0000000..968edf2
Binary files /dev/null and b/gesturelock/src/main/res/drawable-hdpi/lock_pattern_node_pressed.png differ
diff --git a/gesturelock/src/main/res/drawable-hdpi/user_logo.png b/gesturelock/src/main/res/drawable-hdpi/user_logo.png
new file mode 100755
index 0000000..302fcbb
Binary files /dev/null and b/gesturelock/src/main/res/drawable-hdpi/user_logo.png differ
diff --git a/gesturelock/src/main/res/layout/activity_gesture_edit.xml b/gesturelock/src/main/res/layout/activity_gesture_edit.xml
new file mode 100755
index 0000000..7d572f4
--- /dev/null
+++ b/gesturelock/src/main/res/layout/activity_gesture_edit.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gesturelock/src/main/res/layout/activity_gesture_verify.xml b/gesturelock/src/main/res/layout/activity_gesture_verify.xml
new file mode 100755
index 0000000..065a1ff
--- /dev/null
+++ b/gesturelock/src/main/res/layout/activity_gesture_verify.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gesturelock/src/main/res/layout/activity_main_gesture.xml b/gesturelock/src/main/res/layout/activity_main_gesture.xml
new file mode 100755
index 0000000..2f5a98b
--- /dev/null
+++ b/gesturelock/src/main/res/layout/activity_main_gesture.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gesturelock/src/main/res/values/strings.xml b/gesturelock/src/main/res/values/strings.xml
new file mode 100644
index 0000000..6bab342
--- /dev/null
+++ b/gesturelock/src/main/res/values/strings.xml
@@ -0,0 +1,12 @@
+
+ GestureLock
+
+ 设置手势密码
+ 绘制解锁图案
+ 再次绘制解锁图案
+ 忘记手势密码?
+ 用其他账号登录
+ 绘制解锁图案
+ 设置手势密码,防止他人未经授权查看
+ 重新设置手势密码
+
diff --git a/gesturelock/src/test/java/com/wlj/gesturelock/ExampleUnitTest.java b/gesturelock/src/test/java/com/wlj/gesturelock/ExampleUnitTest.java
new file mode 100644
index 0000000..c3d7d9f
--- /dev/null
+++ b/gesturelock/src/test/java/com/wlj/gesturelock/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.wlj.gesturelock;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..aac7c9b
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..04e285f
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Dec 28 10:00:20 PST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..f131930
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':base', ':gesturelock', ':third'
diff --git a/third/.gitignore b/third/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/third/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/third/build.gradle b/third/build.gradle
new file mode 100644
index 0000000..69d3a47
--- /dev/null
+++ b/third/build.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.3"
+
+ defaultConfig {
+ minSdkVersion 15
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
+ compile 'com.android.support:appcompat-v7:23.4.0'
+ compile 'com.android.support:support-v4:23.4.0'
+ testCompile 'junit:junit:4.12'
+ compile files('libs/mta-sdk-1.6.2.jar')
+ compile files('libs/open_sdk_r5756.jar')
+ compile files('libs/libammsdk.jar')
+ compile project(path: ':base')
+ compile files('libs/weiboSDKCore_3.1.4.jar')
+}
diff --git a/third/libs/libammsdk.jar b/third/libs/libammsdk.jar
new file mode 100755
index 0000000..7d6300f
Binary files /dev/null and b/third/libs/libammsdk.jar differ
diff --git a/third/libs/mta-sdk-1.6.2.jar b/third/libs/mta-sdk-1.6.2.jar
new file mode 100755
index 0000000..49b7787
Binary files /dev/null and b/third/libs/mta-sdk-1.6.2.jar differ
diff --git a/third/libs/open_sdk_r5756.jar b/third/libs/open_sdk_r5756.jar
new file mode 100755
index 0000000..72daab6
Binary files /dev/null and b/third/libs/open_sdk_r5756.jar differ
diff --git a/third/libs/weiboSDKCore_3.1.4.jar b/third/libs/weiboSDKCore_3.1.4.jar
new file mode 100755
index 0000000..b2d7906
Binary files /dev/null and b/third/libs/weiboSDKCore_3.1.4.jar differ
diff --git a/third/proguard-rules.pro b/third/proguard-rules.pro
new file mode 100644
index 0000000..7de1e98
--- /dev/null
+++ b/third/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/wlj/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/third/src/androidTest/java/com/hd/wlj/third/ExampleInstrumentedTest.java b/third/src/androidTest/java/com/hd/wlj/third/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..640ff6f
--- /dev/null
+++ b/third/src/androidTest/java/com/hd/wlj/third/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.hd.wlj.third;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("com.hd.wlj.third.test", appContext.getPackageName());
+ }
+}
diff --git a/third/src/main/AndroidManifest.xml b/third/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9c2e0e0
--- /dev/null
+++ b/third/src/main/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/third/src/main/java/com/hd/wlj/third/quicklogin/d b/third/src/main/java/com/hd/wlj/third/quicklogin/d
new file mode 100644
index 0000000..e69de29
diff --git a/third/src/main/java/com/hd/wlj/third/quicklogin/wx/WXLogin.java b/third/src/main/java/com/hd/wlj/third/quicklogin/wx/WXLogin.java
new file mode 100644
index 0000000..314ac09
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/quicklogin/wx/WXLogin.java
@@ -0,0 +1,31 @@
+package com.hd.wlj.third.quicklogin.wx;
+
+import android.content.Context;
+
+import com.hd.wlj.third.share.Constants;
+import com.tencent.mm.sdk.modelmsg.SendAuth;
+import com.tencent.mm.sdk.openapi.IWXAPI;
+import com.tencent.mm.sdk.openapi.WXAPIFactory;
+
+/**
+ * Created by wlj on 2016/10/26.
+ */
+
+public class WXLogin {
+
+
+ private final IWXAPI api;
+
+ public WXLogin(Context context) {
+ api = WXAPIFactory.createWXAPI(context, Constants.WX_APP_ID);
+ }
+
+ public void login(){
+ // send oauth request
+ SendAuth.Req req = new SendAuth.Req();
+ req.scope = "snsapi_userinfo";
+ req.state = "login";
+ api.sendReq(req);
+
+ }
+}
diff --git a/third/src/main/java/com/hd/wlj/third/share/Constants.java b/third/src/main/java/com/hd/wlj/third/share/Constants.java
new file mode 100755
index 0000000..9b6d491
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/Constants.java
@@ -0,0 +1,27 @@
+package com.hd.wlj.third.share;
+
+import com.wlj.base.web.BaseURL;
+
+public class Constants
+{
+
+ public static String Code = "code";
+ public static final String QQ_APP_ID = "1104829131";
+ public static final String SS_APP_KEY = "2523262267";
+ public static final String SS_REDIRECT_URL = "http://www.sina.com";
+ public static final String SS_SCOPE = "email,direct_messages_read,direct_messages_write,friendships_groups_read,friendships_groups_write,statuses_to_me_read,follow_app_official_microblog,invitation_write";
+ public static final String WX_APP_ID = "wx3876877998bb22e6";
+ public static final String WX_AppSecret = "edbea80d435d3f79fddacb1ba948225a";
+ public static String getAccess_tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
+ "appid="+ WX_APP_ID +
+ "&secret="+WX_AppSecret +
+ "&grant_type=authorization_code";
+
+
+ public static String Host = BaseURL.HOST;
+ public static String shoucang;
+ public static String shoucang_remove;
+ public static String fenxiangtarget;
+ public static String qq_targetUrl = "";
+
+}
\ No newline at end of file
diff --git a/third/src/main/java/com/hd/wlj/third/share/ShareModle.java b/third/src/main/java/com/hd/wlj/third/share/ShareModle.java
new file mode 100755
index 0000000..f5a42d0
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/ShareModle.java
@@ -0,0 +1,75 @@
+package com.hd.wlj.third.share;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import com.wlj.base.bean.Base;
+import com.wlj.base.web.HttpPost;
+
+import java.io.IOException;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class ShareModle extends Base {
+ private static final int THUMB_SIZE = 150;
+ private static final long serialVersionUID = -5534536105095669110L;
+ private String content;
+ private String name;
+ private String pic;
+ private int resPic;
+
+
+ public String getContent() {
+ return this.content;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getPic() {
+ return this.pic;
+ }
+
+ public Bitmap getPicBitmap() {
+
+ try {
+ Bitmap localBitmap1 = BitmapFactory.decodeStream(new HttpPost("http://121.40.177.251:6940" + this.pic).getInputStream());
+ if (localBitmap1 != null) {
+ Bitmap localBitmap3 = Bitmap.createScaledBitmap(localBitmap1, THUMB_SIZE, THUMB_SIZE, true);
+ localBitmap1.recycle();
+ return localBitmap3;
+ }
+ } catch (IOException localIOException) {
+ localIOException.printStackTrace();
+ }
+ return null;
+ }
+
+ public int getResPic() {
+ return this.resPic;
+ }
+
+ public Base parse(JSONObject paramJSONObject) throws JSONException {
+ return null;
+ }
+
+ public void setContent(String paramString) {
+
+ this.content = paramString;
+ }
+
+ public void setName(String paramString) {
+ this.name = paramString;
+ }
+
+ public void setPic(String paramString) {
+
+ this.pic = paramString;
+ }
+
+ public void setResPic(int paramInt) {
+ this.resPic = paramInt;
+ }
+}
\ No newline at end of file
diff --git a/third/src/main/java/com/hd/wlj/third/share/ShareUI.java b/third/src/main/java/com/hd/wlj/third/share/ShareUI.java
new file mode 100755
index 0000000..77184d6
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/ShareUI.java
@@ -0,0 +1,220 @@
+package com.hd.wlj.third.share;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.util.Base64;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.WindowManager.LayoutParams;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.GridView;
+import android.widget.TextView;
+
+import com.hd.wlj.third.R;
+import com.hd.wlj.third.share.qq.QQshare;
+import com.hd.wlj.third.share.sina.SinaShare;
+import com.hd.wlj.third.share.weixin.WeiXinShare;
+import com.sina.weibo.sdk.api.share.IWeiboShareAPI;
+import com.wlj.base.adapter.CommonAdapter;
+import com.wlj.base.adapter.ViewHolder;
+import com.wlj.base.bean.Base;
+import com.wlj.base.util.DpAndPx;
+import com.wlj.base.util.MathUtil;
+import com.wlj.base.util.img.ImageFileCache;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ShareUI {
+ private Activity activity;
+ private CommonAdapter commonAdapter;
+ private TextView fenXiangView;
+ private List mDatas;
+ public QQshare mQQshare;
+ private ShareModle mShareModle;
+ private SinaShare mSinaShare;
+ private WeiXinShare mWeiXinShare;
+ private String[] names = {"QQ好友","QQ空间","腾讯微博","新浪微博","微信好友","朋友圈",};
+ private int[] pics = {R.drawable.logo_qq,R.drawable.logo_qzone,R.drawable.logo_tencentweibo,R.drawable.logo_sinaweibo,R.drawable.logo_wechat,R.drawable.logo_wechatmoments,};
+
+ private Animation translate_Animation;
+
+ public ShareUI(Activity activity,ShareModle mShareModle){
+ this.activity = activity;
+ this.mShareModle = mShareModle;
+
+ translate_Animation = AnimationUtils.loadAnimation(activity,R.anim.slide_out_bottom);
+
+ mQQshare = new QQshare(activity,mShareModle);
+ mWeiXinShare = new WeiXinShare(activity);
+
+ mDatas = new ArrayList ();
+
+ for (int i = 0; i < names.length; i++) {
+
+ ShareModle sm = new ShareModle();
+ sm.setName(names[i]);
+ sm.setResPic(pics[i]);
+ mDatas.add(sm);
+ }
+
+// mSinaShare = new SinaShare() {
+// @Override
+// public void onnewintent(IWeiboShareAPI paramIWeiboShareAPI) {
+//
+// }
+// };
+ }
+
+ private void setTopDrawable(TextView paramTextView) {
+ Drawable localDrawable = paramTextView.getContext().getResources().getDrawable(MathUtil.parseInteger(paramTextView.getTag() + ""));
+ localDrawable.setBounds(0, 0, localDrawable.getMinimumWidth(), localDrawable.getMinimumHeight());
+ paramTextView.setCompoundDrawables(null, localDrawable, null, null);
+ }
+
+ public void callwebShouChang(String paramString, View paramView, int paramInt) {
+
+ }
+
+ public TextView getFenXiangView() {
+ return this.fenXiangView;
+ }
+
+ public void setFenXiangView(TextView paramTextView) {
+ this.fenXiangView = paramTextView;
+ }
+
+
+ public void showdialog(Boolean paramBoolean) {
+ final Dialog localDialog = new Dialog(this.activity, R.style.dialog);
+ View localView = LayoutInflater.from(activity).inflate(R.layout.share, null);
+ localDialog.setContentView(localView);
+ localDialog.show();
+ Display localDisplay = this.activity.getWindowManager().getDefaultDisplay();
+ LayoutParams localLayoutParams = localDialog.getWindow().getAttributes();
+ localLayoutParams.height = (localDisplay.getHeight() - DpAndPx.dpToPx(this.activity, 20.0F));
+ localLayoutParams.width = localDisplay.getWidth();
+ localDialog.getWindow().setAttributes(localLayoutParams);
+ localView.findViewById(R.id.nulltr).setOnClickListener(new OnClickListener() {
+ public void onClick(View paramAnonymousView) {
+
+ localDialog.dismiss();
+ }
+ });
+ localView.findViewById(R.id.space).setAnimation(this.translate_Animation);
+ localView.findViewById(R.id.space).startAnimation(this.translate_Animation);
+ localView.findViewById(R.id.canl).setOnClickListener(new OnClickListener() {
+
+ public void onClick(View paramAnonymousView) {
+ localDialog.dismiss();
+ }
+ });
+
+ TextView localTextView = (TextView) localView.findViewById(R.id.shouchang_xx);
+ if (!paramBoolean.booleanValue()) {
+ int i = R.drawable.shouchang_xx;
+ localTextView.setTag(Integer.valueOf(i));
+ setTopDrawable(localTextView);
+ localTextView.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+
+ String str = Constants.shoucang;
+ int j = R.drawable.shouchang_xx;
+
+ int i = Integer.parseInt(v.getTag() + "");
+
+ if (R.drawable.shouchang_xx == i) {
+
+ j = R.drawable.shoucang_xx_red;
+ } else {
+ str = Constants.shoucang_remove;
+ }
+
+ ShareUI.this.callwebShouChang(str, v, j);
+
+ }
+ });
+ }
+ //复制链接
+ localView.findViewById(R.id.fuzhilianjie).setOnClickListener(new OnClickListener() {
+
+ public void onClick(View paramAnonymousView) {
+
+ Activity localActivity = ShareUI.this.activity;
+ ((ClipboardManager) localActivity.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("simple text", Constants.qq_targetUrl + mShareModle.getId()));
+ localDialog.dismiss();
+ }
+ });
+
+ GridView localGridView = (GridView) localView.findViewById(R.id.sharegridView1);
+ this.commonAdapter = new CommonAdapter (this.activity, this.mDatas, R.layout.item_share_gridview) {
+
+ public View getListItemview(ViewHolder paramAnonymousViewHolder, View v, Base base, int paramAnonymousInt, ViewGroup viewGroup) {
+
+ ShareModle localShareModle = (ShareModle) base;
+ paramAnonymousViewHolder.setText(R.id.textView1, localShareModle.getName());
+ paramAnonymousViewHolder.setImageResource(R.id.imageview, localShareModle.getResPic());
+ v.setTag(R.id.tag_first, base);
+ return null;
+ }
+ };
+ localGridView.setAdapter(this.commonAdapter);
+ localGridView.setOnItemClickListener(new OnItemClickListener() {
+
+ public void onItemClick(AdapterView> paramAnonymousAdapterView, View view, int postion, long paramAnonymousLong) {
+ switch (postion) {
+ case 0:
+ ShareUI.this.mQQshare.login(0);
+ break;
+ case 1:
+ ShareUI.this.mQQshare.login(1);
+ break;
+ case 2:
+ ShareUI.this.mQQshare.login(2);
+ break;
+ case 3:
+ mSinaShare.sendMultiMessage();
+ break;
+ case 4:
+ //微信
+ weixinShare(false);
+ break;
+ case 5:
+ //微信盆友圈
+ weixinShare(true);
+ break;
+
+ }
+
+ }
+
+ private void weixinShare(Boolean isFriend) {
+ mWeiXinShare.setPengyouquan(isFriend);
+ String str3 = new String(Base64.decode(mShareModle.getContent(), 0)).replaceAll("<[^>]*>", "");
+ String str4 = new ImageFileCache().getPath("http://121.40.177.251:6940" + mShareModle.getPic());
+ if (!new File(str4).exists()) {
+ mWeiXinShare.sendText(str3);
+ } else {
+ mWeiXinShare.sendWebPage(Constants.fenxiangtarget + mShareModle.getId(), mShareModle.getName(), str3, BitmapFactory.decodeFile(str4));
+ }
+ }
+
+
+ });
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/third/src/main/java/com/hd/wlj/third/share/qq/BaseUIListener.java b/third/src/main/java/com/hd/wlj/third/share/qq/BaseUIListener.java
new file mode 100755
index 0000000..14ba7e1
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/qq/BaseUIListener.java
@@ -0,0 +1,84 @@
+package com.hd.wlj.third.share.qq;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+
+import com.tencent.tauth.IUiListener;
+import com.tencent.tauth.UiError;
+import com.wlj.base.util.UIHelper;
+
+import org.json.JSONObject;
+
+public class BaseUIListener
+ implements IUiListener {
+ private static final int ON_CANCEL = 2;
+ private static final int ON_COMPLETE = 0;
+ private static final int ON_ERROR = 1;
+ private Context mContext;
+
+ private Handler mHandler = new Handler() {
+ public void handleMessage(Message paramAnonymousMessage) {
+ switch (paramAnonymousMessage.what) {
+ case 0:
+ JSONObject localJSONObject = (JSONObject) paramAnonymousMessage.obj;
+ UIHelper.toastMessage(mContext, localJSONObject.toString());
+ UIHelper.loadingClose();
+ return;
+ case 1:
+ UiError localUiError = (UiError) paramAnonymousMessage.obj;
+ UIHelper.toastMessage(mContext, "errorMsg:" + localUiError.errorMessage + "errorDetail:" + localUiError.errorDetail);
+ UIHelper.loadingClose();
+ return;
+ case 2:
+ }
+ UIHelper.toastMessage(mContext, "onCancel");
+ }
+ };
+ private boolean mIsCaneled;
+ private String mScope;
+
+ public BaseUIListener(Context paramContext) {
+ this.mContext = paramContext;
+ }
+
+ public BaseUIListener(Context paramContext, String paramString) {
+ this.mContext = paramContext;
+ this.mScope = paramString;
+ }
+
+
+ public void cancel() {
+ this.mIsCaneled = true;
+ }
+
+ public Context getmContext() {
+ return this.mContext;
+ }
+
+ public void onCancel() {
+ Message localMessage = this.mHandler.obtainMessage();
+ localMessage.what = 2;
+ this.mHandler.sendMessage(localMessage);
+ }
+
+ public void onComplete(Object paramObject) {
+
+ Message localMessage = this.mHandler.obtainMessage();
+ localMessage.what = 0;
+ localMessage.obj = paramObject;
+ this.mHandler.sendMessage(localMessage);
+ }
+
+ public void onError(UiError paramUiError) {
+ Message localMessage = this.mHandler.obtainMessage();
+ localMessage.what = 1;
+ localMessage.obj = paramUiError;
+ this.mHandler.sendMessage(localMessage);
+ }
+
+ public void setmContext(Context paramContext) {
+
+ this.mContext = paramContext;
+ }
+}
\ No newline at end of file
diff --git a/third/src/main/java/com/hd/wlj/third/share/qq/QQshare.java b/third/src/main/java/com/hd/wlj/third/share/qq/QQshare.java
new file mode 100755
index 0000000..208a3e1
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/qq/QQshare.java
@@ -0,0 +1,250 @@
+package com.hd.wlj.third.share.qq;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.widget.Toast;
+
+import com.hd.wlj.third.R;
+import com.hd.wlj.third.share.Constants;
+import com.hd.wlj.third.share.ShareModle;
+import com.tencent.open.t.Weibo;
+import com.tencent.tauth.IUiListener;
+import com.tencent.tauth.Tencent;
+import com.tencent.tauth.UiError;
+import com.wlj.base.util.UIHelper;
+import com.wlj.base.util.img.ImageFileCache;
+import com.wlj.base.web.BaseURL;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+public class QQshare implements IUiListener
+{
+ public static final int QZoneShare = 1;
+ public static final int QqShare = 0;
+ public static Tencent mTencent;
+ public static final int weibo = 2;
+ private String content = "";
+ public IUiListener loginListener;
+ private Activity mActivity;
+ private ShareModle mShareModle;
+ private Weibo mWeibo = null;
+ private int shareType = 1;
+ private int tempType = -1;
+
+ public QQshare(Activity mActivity, ShareModle mShareModle)
+ {
+ this.mShareModle = mShareModle;
+ this.mActivity = mActivity;
+
+ // Tencent类是SDK的主要实现类,开发者可通过Tencent类访问腾讯开放的OpenAPI。
+ // 其中APP_ID是分配给第三方应用的appid,类型为String。
+ mTencent = Tencent.createInstance(Constants.QQ_APP_ID, mActivity);
+ // 1.4版本:此处需新增参数,传入应用程序的全局context,可通过activity的getApplicationContext方法获取
+
+ loginListener = new BaseUiListener() {
+ @Override
+ public void doComplete(JSONObject values) {
+ initOpenidAndToken(values);
+ onClickAddPicUrlTweet();
+ }
+ };
+
+ mWeibo = new Weibo(mActivity, mTencent.getQQToken());
+ }
+
+ private void QZoneShare()
+ {
+
+ Bundle localBundle = new Bundle();
+ localBundle.putInt("req_type", 1);
+ localBundle.putString("title", this.mShareModle.getName());
+ localBundle.putString("summary", this.content);
+ localBundle.putString("targetUrl", Constants.qq_targetUrl + this.mShareModle.getId());
+ ArrayList localArrayList = new ArrayList();
+ localArrayList.add(new ImageFileCache().getPath(this.mShareModle.getPic()));
+ localBundle.putStringArrayList("imageUrl", localArrayList);
+ mTencent.shareToQzone(this.mActivity, localBundle, this);
+ }
+
+ public static void initOpenidAndToken(JSONObject paramJSONObject)
+ {
+ String str1 = paramJSONObject.optString("access_token");
+ String str2 = paramJSONObject.optString("expires_in");
+ String str3 = paramJSONObject.optString("openid");
+ if ((!TextUtils.isEmpty(str1)) && (!TextUtils.isEmpty(str2)) && (!TextUtils.isEmpty(str3)))
+ {
+ mTencent.setAccessToken(str1, str2);
+ mTencent.setOpenId(str3);
+ }
+
+
+ }
+
+ private void onClickAddPicUrlTweet()
+ {
+ String str = new ImageFileCache().getPath("http://121.40.177.251:6940picpath");
+ this.mWeibo.sendPicText(this.content, str, new TQQApiListener("add_pic_t", false, this.mActivity));
+ UIHelper.loading("请稍后……", this.mActivity);
+ }
+
+ public static boolean ready(Context paramContext)
+ {
+ if (mTencent == null)
+ return false;
+ if ((mTencent.isSessionValid()) && (mTencent.getQQToken().getOpenId() != null)){
+
+
+ return true;
+ }else{
+ Toast.makeText(paramContext, "login and get openId first, please!", Toast.LENGTH_SHORT).show();
+ }
+ return false;
+
+ }
+
+ private void shareQQ()
+ {
+
+ Bundle localBundle = new Bundle();
+ localBundle.putString("title", this.mShareModle.getName());
+ localBundle.putString("targetUrl", Constants.qq_targetUrl+ this.mShareModle.getId());
+ localBundle.putString("summary", this.content);
+ localBundle.putString("imageUrl", BaseURL.HOST + this.mShareModle.getPic());
+ localBundle.putString("appName", this.mActivity.getString(R.string.app_name));
+ localBundle.putInt("req_type", this.shareType);
+ mTencent.shareToQQ(this.mActivity, localBundle, this);
+ }
+
+ public void login(int paramInt) {
+ while (true) {
+
+
+ this.tempType = paramInt;
+ switch (this.tempType) {
+ case 0:
+ shareQQ();
+ break;
+ case 1:
+ QZoneShare();
+ break;
+ case 2:
+ if (!mTencent.isSessionValid())
+ mTencent.login(this.mActivity, "all", this.loginListener);
+ else
+ onClickAddPicUrlTweet();
+ break;
+ }
+
+
+ }
+ }
+
+ public void onClickAddTweet()
+ {
+ this.mWeibo.sendText("test add tweet", new TQQApiListener("add_t", false, this.mActivity));
+ UIHelper.loading("正在加载……", this.mActivity);
+ }
+
+ public void onComplete(Object paramObject)
+ {
+ UIHelper.toastMessage(this.mActivity.getApplicationContext(), "分享成功");
+ }
+
+ public void onError(UiError paramUiError)
+ {
+ UIHelper.toastMessage(this.mActivity.getApplicationContext(), paramUiError.errorMessage);
+ }
+
+ @Override
+ public void onCancel() {
+ UIHelper.toastMessage(mActivity, "onCancel: ");
+ }
+
+ public class BaseUiListener implements IUiListener
+ {
+
+ public BaseUiListener()
+ {
+ }
+
+ public void doComplete(JSONObject paramJSONObject)
+ {
+ }
+
+ public void onCancel()
+ {
+ UIHelper.toastMessage(mActivity, "onCancel: ");
+ }
+
+ public void onComplete(Object paramObject)
+ {
+
+ if (paramObject == null)
+ {
+ UIHelper.toastMessage(mActivity, "返回为空, 登录失败");
+ return;
+ }
+ JSONObject localJSONObject = (JSONObject)paramObject;
+ if ((localJSONObject != null) && (localJSONObject.length() == 0))
+ {
+ UIHelper.toastMessage(mActivity, "返回为空,登录失败");
+ return;
+ }
+ UIHelper.toastMessage(mActivity, "登录成功");
+ doComplete((JSONObject)paramObject);
+ }
+
+ public void onError(UiError paramUiError)
+ {
+ UIHelper.toastMessage(mActivity, "onError: " + paramUiError.errorDetail);
+ }
+ }
+
+ public class TQQApiListener extends BaseUIListener
+ {
+ private Activity mActivity;
+ private Boolean mNeedReAuth = Boolean.valueOf(false);
+ private String mScope = "all";
+
+ public TQQApiListener(String paramBoolean, boolean paramActivity, Activity arg4)
+ {
+ super(arg4);
+ this.mScope = paramBoolean;
+ this.mNeedReAuth = Boolean.valueOf(paramActivity);
+ this.mActivity = arg4;
+ }
+
+ public void onComplete(Object paramObject)
+ {
+ final Activity localActivity = mActivity;
+ try
+ {
+ int i = ((JSONObject)paramObject).getInt("ret");
+ if (i == 0)
+ UIHelper.toastMessage(localActivity, "分享成功");
+
+ UIHelper.loadingClose();
+
+ if ((i == 100030) && (this.mNeedReAuth.booleanValue()))
+ localActivity.runOnUiThread(new Runnable()
+ {
+ public void run()
+ {
+ QQshare.mTencent.reAuth(localActivity, "all", new BaseUIListener(localActivity));
+ }
+ });
+
+ }
+ catch (JSONException localJSONException)
+ {
+ localJSONException.printStackTrace();
+ UIHelper.toastMessage(localActivity, "onComplete() JSONException: " + paramObject.toString());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/third/src/main/java/com/hd/wlj/third/share/sina/AccessTokenKeeper.java b/third/src/main/java/com/hd/wlj/third/share/sina/AccessTokenKeeper.java
new file mode 100644
index 0000000..594d788
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/sina/AccessTokenKeeper.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2010-2013 The SINA WEIBO Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.hd.wlj.third.share.sina;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+import com.sina.weibo.sdk.auth.Oauth2AccessToken;
+
+/**
+ * 该类定义了微博授权时所需要的参数。
+ *
+ * @author SINA
+ * @since 2013-10-07
+ */
+public class AccessTokenKeeper {
+ private static final String PREFERENCES_NAME = "com_weibo_sdk_android";
+
+ private static final String KEY_UID = "uid";
+ private static final String KEY_ACCESS_TOKEN = "access_token";
+ private static final String KEY_EXPIRES_IN = "expires_in";
+ private static final String KEY_REFRESH_TOKEN = "refresh_token";
+
+ /**
+ * 保存 Token 对象到 SharedPreferences。
+ *
+ * @param context 应用程序上下文环境
+ * @param token Token 对象
+ */
+ public static void writeAccessToken(Context context, Oauth2AccessToken token) {
+ if (null == context || null == token) {
+ return;
+ }
+
+ SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);
+ Editor editor = pref.edit();
+ editor.putString(KEY_UID, token.getUid());
+ editor.putString(KEY_ACCESS_TOKEN, token.getToken());
+ editor.putString(KEY_REFRESH_TOKEN, token.getRefreshToken());
+ editor.putLong(KEY_EXPIRES_IN, token.getExpiresTime());
+ editor.commit();
+ }
+
+ /**
+ * 从 SharedPreferences 读取 Token 信息。
+ *
+ * @param context 应用程序上下文环境
+ *
+ * @return 返回 Token 对象
+ */
+ public static Oauth2AccessToken readAccessToken(Context context) {
+ if (null == context) {
+ return null;
+ }
+
+ Oauth2AccessToken token = new Oauth2AccessToken();
+ SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);
+ token.setUid(pref.getString(KEY_UID, ""));
+ token.setToken(pref.getString(KEY_ACCESS_TOKEN, ""));
+ token.setRefreshToken(pref.getString(KEY_REFRESH_TOKEN, ""));
+ token.setExpiresTime(pref.getLong(KEY_EXPIRES_IN, 0));
+
+ return token;
+ }
+
+ /**
+ * 清空 SharedPreferences 中 Token信息。
+ *
+ * @param context 应用程序上下文环境
+ */
+ public static void clear(Context context) {
+ if (null == context) {
+ return;
+ }
+
+ SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);
+ Editor editor = pref.edit();
+ editor.clear();
+ editor.commit();
+ }
+}
diff --git a/third/src/main/java/com/hd/wlj/third/share/sina/SinaShare.java b/third/src/main/java/com/hd/wlj/third/share/sina/SinaShare.java
new file mode 100755
index 0000000..f9d30d0
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/sina/SinaShare.java
@@ -0,0 +1,116 @@
+package com.hd.wlj.third.share.sina;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.widget.ImageView;
+
+import com.hd.wlj.third.share.Constants;
+import com.sina.weibo.sdk.api.ImageObject;
+import com.sina.weibo.sdk.api.TextObject;
+import com.sina.weibo.sdk.api.WeiboMultiMessage;
+import com.sina.weibo.sdk.api.share.IWeiboShareAPI;
+import com.sina.weibo.sdk.api.share.SendMultiMessageToWeiboRequest;
+import com.sina.weibo.sdk.api.share.WeiboShareSDK;
+import com.sina.weibo.sdk.auth.AuthInfo;
+import com.sina.weibo.sdk.auth.Oauth2AccessToken;
+import com.sina.weibo.sdk.auth.WeiboAuthListener;
+import com.sina.weibo.sdk.exception.WeiboException;
+import com.wlj.base.util.UIHelper;
+
+public abstract class SinaShare {
+ private String dateText;
+ private Bitmap image;
+ private Activity mActivity;
+ private ImageView mImageView;
+ private IWeiboShareAPI mWeiboShareAPI;
+
+ public SinaShare(Activity paramActivity, Bundle savedInstanceState) {
+ this.mActivity = paramActivity;
+ // 创建微博分享接口实例
+ mWeiboShareAPI = WeiboShareSDK.createWeiboAPI(mActivity.getApplicationContext(), Constants.SS_APP_KEY);
+
+ // 注册第三方应用到微博客户端中,注册成功后该应用将显示在微博的应用列表中。
+ // 但该附件栏集成分享权限需要合作申请,详情请查看 Demo 提示
+ // NOTE:请务必提前注册,即界面初始化的时候或是应用程序初始化时,进行注册
+ mWeiboShareAPI.registerApp();
+
+ // 当 Activity 被重新初始化时(该 Activity 处于后台时,可能会由于内存不足被杀掉了),
+ // 需要调用 {@link IWeiboShareAPI#handleWeiboResponse} 来接收微博客户端返回的数据。
+ // 执行成功,返回 true,并调用 {@link IWeiboHandler.Response#onResponse};
+ // 失败返回 false,不调用上述回调
+ if (savedInstanceState != null) {
+ mWeiboShareAPI.handleWeiboResponse(mActivity.getIntent(), new myResponse(mActivity));
+ }
+
+ onnewintent(mWeiboShareAPI);
+ }
+
+ // @Override
+// protected void onNewIntent(Intent intent) {
+// super.onNewIntent(intent);
+//
+// // 从当前应用唤起微博并进行分享后,返回到当前应用时,需要在此处调用该函数
+// // 来接收微博客户端返回的数据;执行成功,返回 true,并调用
+// // {@link IWeiboHandler.Response#onResponse};失败返回 false,不调用上述回调
+// mWeiboShareAPI.handleWeiboResponse(intent, this);
+// }
+ private ImageObject getImageObj() {
+ ImageObject localImageObject = new ImageObject();
+ localImageObject.setImageObject(this.image);
+ return localImageObject;
+ }
+
+ private TextObject getTextObj() {
+ this.dateText = this.dateText.replaceAll("<[^>]*>", "");
+ TextObject localTextObject = new TextObject();
+ localTextObject.text = this.dateText.substring(0, Math.min(140, this.dateText.length()));
+ return localTextObject;
+ }
+
+ public abstract void onnewintent(IWeiboShareAPI paramIWeiboShareAPI);
+
+ public void sendMultiMessage() {
+ WeiboMultiMessage localWeiboMultiMessage = new WeiboMultiMessage();
+ localWeiboMultiMessage.textObject = getTextObj();
+
+ if (this.image != null)
+ localWeiboMultiMessage.imageObject = getImageObj();
+
+ SendMultiMessageToWeiboRequest localSendMultiMessageToWeiboRequest = new SendMultiMessageToWeiboRequest();
+ localSendMultiMessageToWeiboRequest.transaction = String.valueOf(System.currentTimeMillis());
+ localSendMultiMessageToWeiboRequest.multiMessage = localWeiboMultiMessage;
+ AuthInfo localAuthInfo = new AuthInfo(this.mActivity, Constants.SS_APP_KEY, Constants.SS_REDIRECT_URL, Constants.SS_SCOPE);
+ Oauth2AccessToken localOauth2AccessToken = AccessTokenKeeper.readAccessToken(this.mActivity);
+ String str = "";
+ if (localOauth2AccessToken != null)
+ str = localOauth2AccessToken.getToken();
+ this.mWeiboShareAPI.sendRequest(this.mActivity, localSendMultiMessageToWeiboRequest, localAuthInfo, str, new WeiboAuthListener() {
+ public void onCancel() {
+
+ UIHelper.toastMessage(mActivity, "取消Auth");
+ }
+
+ public void onComplete(Bundle paramAnonymousBundle) {
+ Oauth2AccessToken localOauth2AccessToken = Oauth2AccessToken.parseAccessToken(paramAnonymousBundle);
+ AccessTokenKeeper.writeAccessToken(mActivity, localOauth2AccessToken);
+ UIHelper.toastMessage(mActivity, "成功");
+ }
+
+ public void onWeiboException(WeiboException paramAnonymousWeiboException) {
+
+ UIHelper.toastMessage(mActivity, "Auth异常" + paramAnonymousWeiboException.getLocalizedMessage());
+ }
+ });
+ }
+
+ public void setDateText(String paramString) {
+
+ this.dateText = paramString;
+ }
+
+ public void setmBitmap(Bitmap paramBitmap) {
+
+ this.image = paramBitmap;
+ }
+}
\ No newline at end of file
diff --git a/third/src/main/java/com/hd/wlj/third/share/sina/myResponse.java b/third/src/main/java/com/hd/wlj/third/share/sina/myResponse.java
new file mode 100755
index 0000000..31f9e86
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/sina/myResponse.java
@@ -0,0 +1,37 @@
+package com.hd.wlj.third.share.sina;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import com.hd.wlj.third.R;
+import com.orhanobut.logger.Logger;
+import com.sina.weibo.sdk.api.share.BaseResponse;
+import com.sina.weibo.sdk.api.share.IWeiboHandler;
+
+public class myResponse
+ implements IWeiboHandler.Response
+{
+ private Context mContext;
+
+ public myResponse(Context paramContext)
+ {
+ this.mContext = paramContext;
+ Logger.e("myResponse", new Object[] { "还不调用啊" });
+ }
+
+ public void onResponse(BaseResponse paramBaseResponse)
+ {
+ switch (paramBaseResponse.errCode)
+ {
+
+ case 0:
+ Toast.makeText(this.mContext, R.string.weibosdk_demo_toast_share_success, Toast.LENGTH_SHORT).show();
+ return;
+ case 1:
+ Toast.makeText(this.mContext, R.string.weibosdk_demo_toast_share_canceled, Toast.LENGTH_SHORT).show();
+ return;
+ case 2:
+ }
+ Toast.makeText(this.mContext, this.mContext.getString(R.string.weibosdk_demo_toast_share_failed) + "Error Message: " + paramBaseResponse.errMsg, Toast.LENGTH_SHORT).show();
+ }
+}
\ No newline at end of file
diff --git a/third/src/main/java/com/hd/wlj/third/share/weixin/WeiXinShare.java b/third/src/main/java/com/hd/wlj/third/share/weixin/WeiXinShare.java
new file mode 100755
index 0000000..992cae2
--- /dev/null
+++ b/third/src/main/java/com/hd/wlj/third/share/weixin/WeiXinShare.java
@@ -0,0 +1,180 @@
+package com.hd.wlj.third.share.weixin;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.widget.Toast;
+
+import com.hd.wlj.third.share.Constants;
+import com.tencent.mm.sdk.modelmsg.SendMessageToWX;
+import com.tencent.mm.sdk.modelmsg.WXImageObject;
+import com.tencent.mm.sdk.modelmsg.WXMediaMessage;
+import com.tencent.mm.sdk.modelmsg.WXTextObject;
+import com.tencent.mm.sdk.modelmsg.WXWebpageObject;
+import com.tencent.mm.sdk.openapi.IWXAPI;
+import com.tencent.mm.sdk.openapi.WXAPIFactory;
+import com.wlj.base.util.StringUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URL;
+
+public class WeiXinShare {
+
+ private static final int THUMB_SIZE = 150;
+ private IWXAPI api;
+ private Activity mActivity;
+ private boolean pengyouquan;
+
+ public WeiXinShare(Activity paramActivity) {
+ this.mActivity = paramActivity;
+ regToWX();
+ }
+
+
+ private byte[] bmpToByteArray(Bitmap paramBitmap, boolean paramBoolean) {
+ ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
+ paramBitmap.compress(CompressFormat.PNG, 100, localByteArrayOutputStream);
+ if (paramBoolean)
+ paramBitmap.recycle();
+ byte[] arrayOfByte = localByteArrayOutputStream.toByteArray();
+ try {
+ localByteArrayOutputStream.close();
+ return arrayOfByte;
+ } catch (Exception localException) {
+ while (true)
+ localException.printStackTrace();
+ }
+ }
+
+ private String buildTransaction(String paramString) {
+ return paramString + System.currentTimeMillis();
+ }
+
+ /**
+ *
+ * @param paramBitmap
+ * @return
+ */
+ private WXMediaMessage imgObj(Bitmap paramBitmap) {
+ WXImageObject localWXImageObject = new WXImageObject(paramBitmap);
+ WXMediaMessage localWXMediaMessage = new WXMediaMessage();
+ localWXMediaMessage.mediaObject = localWXImageObject;
+ Bitmap localBitmap = Bitmap.createScaledBitmap(paramBitmap, THUMB_SIZE, THUMB_SIZE, true);
+ paramBitmap.recycle();
+ localWXMediaMessage.thumbData = bmpToByteArray(localBitmap, true);
+ return localWXMediaMessage;
+ }
+
+ /**
+ * itmapFactory.decodeFile(paramString);
+ * @param paramString 本地路径
+ * @return
+ */
+ private WXMediaMessage imgObj(String paramString) {
+ WXImageObject localWXImageObject = new WXImageObject();
+ localWXImageObject.setImagePath(paramString);
+ WXMediaMessage localWXMediaMessage = new WXMediaMessage();
+ localWXMediaMessage.mediaObject = localWXImageObject;
+ Bitmap localBitmap1 = BitmapFactory.decodeFile(paramString);
+ Bitmap localBitmap2 = Bitmap.createScaledBitmap(localBitmap1, THUMB_SIZE, THUMB_SIZE, true);
+ localBitmap1.recycle();
+ localWXMediaMessage.thumbData = bmpToByteArray(localBitmap2, true);
+ return localWXMediaMessage;
+ }
+
+ /**
+ * new URL(paramString).openStream()
+ * @param paramString url 网络地址
+ * @return
+ */
+ private WXMediaMessage imgUrl(String paramString) {
+ WXImageObject localWXImageObject = new WXImageObject();
+ localWXImageObject.imagePath = paramString;
+ WXMediaMessage localWXMediaMessage = new WXMediaMessage();
+ localWXMediaMessage.mediaObject = localWXImageObject;
+ Bitmap localBitmap1 = null;
+ try {
+ localBitmap1 = BitmapFactory.decodeStream(new URL(paramString).openStream());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ Bitmap localBitmap2 = Bitmap.createScaledBitmap(localBitmap1, THUMB_SIZE, THUMB_SIZE, true);
+ localBitmap1.recycle();
+ localWXMediaMessage.thumbData = bmpToByteArray(localBitmap2, true);
+ return localWXMediaMessage;
+ }
+
+ private void regToWX() {
+ this.api = WXAPIFactory.createWXAPI(this.mActivity, Constants.WX_APP_ID, false);
+ this.api.registerApp(Constants.WX_APP_ID);
+ }
+
+ private void sendMessage(WXMediaMessage paramWXMediaMessage) {
+ SendMessageToWX.Req localReq = new SendMessageToWX.Req();
+ localReq.transaction = (System.currentTimeMillis() + "image");
+ localReq.message = paramWXMediaMessage;
+ if (this.pengyouquan) {
+ localReq.scene = SendMessageToWX.Req.WXSceneTimeline;
+ }else{
+ localReq.scene = SendMessageToWX.Req.WXSceneSession;
+ }
+ this.api.sendReq(localReq);
+ }
+
+ private WXMediaMessage textObj(String paramString) {
+ WXTextObject localWXTextObject = new WXTextObject();
+ localWXTextObject.text = paramString;
+ WXMediaMessage localWXMediaMessage = new WXMediaMessage();
+ localWXMediaMessage.mediaObject = localWXTextObject;
+ localWXMediaMessage.description = paramString;
+ return localWXMediaMessage;
+ }
+
+ private WXMediaMessage webPageShare(String paramString1, String paramString2, String paramString3, Bitmap paramBitmap) {
+ if (!this.api.isWXAppInstalled()) {
+ Toast.makeText(this.mActivity, "您还未安装微信客户端", Toast.LENGTH_SHORT).show();
+ return null;
+ }
+ WXWebpageObject localWXWebpageObject = new WXWebpageObject();
+ localWXWebpageObject.webpageUrl = paramString1;
+ WXMediaMessage localWXMediaMessage = new WXMediaMessage(localWXWebpageObject);
+ localWXMediaMessage.title = paramString2.substring(0, Math.min(paramString2.length(), 256));
+ localWXMediaMessage.description = paramString3.substring(0, Math.min(paramString3.length(), 512));
+ if (paramBitmap != null) {
+ Bitmap localBitmap = Bitmap.createScaledBitmap(paramBitmap, THUMB_SIZE, THUMB_SIZE, true);
+ paramBitmap.recycle();
+ localWXMediaMessage.setThumbImage(localBitmap);
+ }
+ return localWXMediaMessage;
+ }
+
+ /**
+ *
+ * @param paramBitmap data
+ * @param localpath 本地地址
+ * @param url 网络地址
+ */
+ public void sendImg(Bitmap paramBitmap, String localpath, String url) {
+
+ if (paramBitmap != null)
+ sendMessage(imgObj(paramBitmap));
+ if (StringUtils.isEmpty(localpath))
+ sendMessage(imgObj(localpath));
+ if(StringUtils.isEmpty(url))
+ sendMessage(imgUrl(url));
+ }
+
+ public void sendText(String paramString) {
+ sendMessage(textObj(paramString));
+ }
+
+ public void sendWebPage(String paramString1, String paramString2, String paramString3, Bitmap paramBitmap) {
+ sendMessage(webPageShare(paramString1, paramString2, paramString3, paramBitmap));
+ }
+
+ public void setPengyouquan(boolean paramBoolean) {
+ this.pengyouquan = paramBoolean;
+ }
+}
\ No newline at end of file
diff --git a/third/src/main/jniLibs/arm64-v8a/libweibosdkcore.so b/third/src/main/jniLibs/arm64-v8a/libweibosdkcore.so
new file mode 100755
index 0000000..94a4567
Binary files /dev/null and b/third/src/main/jniLibs/arm64-v8a/libweibosdkcore.so differ
diff --git a/third/src/main/jniLibs/armeabi-v7a/libweibosdkcore.so b/third/src/main/jniLibs/armeabi-v7a/libweibosdkcore.so
new file mode 100755
index 0000000..a9495b6
Binary files /dev/null and b/third/src/main/jniLibs/armeabi-v7a/libweibosdkcore.so differ
diff --git a/third/src/main/jniLibs/armeabi/libweibosdkcore.so b/third/src/main/jniLibs/armeabi/libweibosdkcore.so
new file mode 100755
index 0000000..2d8fdf9
Binary files /dev/null and b/third/src/main/jniLibs/armeabi/libweibosdkcore.so differ
diff --git a/third/src/main/jniLibs/mips/libweibosdkcore.so b/third/src/main/jniLibs/mips/libweibosdkcore.so
new file mode 100755
index 0000000..8e22226
Binary files /dev/null and b/third/src/main/jniLibs/mips/libweibosdkcore.so differ
diff --git a/third/src/main/jniLibs/mips64/libweibosdkcore.so b/third/src/main/jniLibs/mips64/libweibosdkcore.so
new file mode 100755
index 0000000..d495237
Binary files /dev/null and b/third/src/main/jniLibs/mips64/libweibosdkcore.so differ
diff --git a/third/src/main/jniLibs/x86/libweibosdkcore.so b/third/src/main/jniLibs/x86/libweibosdkcore.so
new file mode 100755
index 0000000..44f794d
Binary files /dev/null and b/third/src/main/jniLibs/x86/libweibosdkcore.so differ
diff --git a/third/src/main/jniLibs/x86_64/libweibosdkcore.so b/third/src/main/jniLibs/x86_64/libweibosdkcore.so
new file mode 100755
index 0000000..a8776bb
Binary files /dev/null and b/third/src/main/jniLibs/x86_64/libweibosdkcore.so differ
diff --git a/third/src/main/res/anim/slide_in_bottom.xml b/third/src/main/res/anim/slide_in_bottom.xml
new file mode 100755
index 0000000..b221e27
--- /dev/null
+++ b/third/src/main/res/anim/slide_in_bottom.xml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/third/src/main/res/anim/slide_in_from_bottom.xml b/third/src/main/res/anim/slide_in_from_bottom.xml
new file mode 100755
index 0000000..558ef5e
--- /dev/null
+++ b/third/src/main/res/anim/slide_in_from_bottom.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/third/src/main/res/anim/slide_out_bottom.xml b/third/src/main/res/anim/slide_out_bottom.xml
new file mode 100755
index 0000000..bddcb67
--- /dev/null
+++ b/third/src/main/res/anim/slide_out_bottom.xml
@@ -0,0 +1,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/third/src/main/res/anim/slide_out_from_bottom.xml b/third/src/main/res/anim/slide_out_from_bottom.xml
new file mode 100755
index 0000000..f68d66a
--- /dev/null
+++ b/third/src/main/res/anim/slide_out_from_bottom.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/third/src/main/res/drawable-xhdpi/fuzhilianjie.png b/third/src/main/res/drawable-xhdpi/fuzhilianjie.png
new file mode 100644
index 0000000..0bfe92b
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/fuzhilianjie.png differ
diff --git a/third/src/main/res/drawable-xhdpi/logo_qq.png b/third/src/main/res/drawable-xhdpi/logo_qq.png
new file mode 100644
index 0000000..612bf2f
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/logo_qq.png differ
diff --git a/third/src/main/res/drawable-xhdpi/logo_qzone.png b/third/src/main/res/drawable-xhdpi/logo_qzone.png
new file mode 100644
index 0000000..1365286
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/logo_qzone.png differ
diff --git a/third/src/main/res/drawable-xhdpi/logo_sinaweibo.png b/third/src/main/res/drawable-xhdpi/logo_sinaweibo.png
new file mode 100644
index 0000000..99e6bfe
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/logo_sinaweibo.png differ
diff --git a/third/src/main/res/drawable-xhdpi/logo_tencentweibo.png b/third/src/main/res/drawable-xhdpi/logo_tencentweibo.png
new file mode 100644
index 0000000..8f589f9
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/logo_tencentweibo.png differ
diff --git a/third/src/main/res/drawable-xhdpi/logo_wechat.png b/third/src/main/res/drawable-xhdpi/logo_wechat.png
new file mode 100644
index 0000000..a4a99cd
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/logo_wechat.png differ
diff --git a/third/src/main/res/drawable-xhdpi/logo_wechatmoments.png b/third/src/main/res/drawable-xhdpi/logo_wechatmoments.png
new file mode 100644
index 0000000..a192766
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/logo_wechatmoments.png differ
diff --git a/third/src/main/res/drawable-xhdpi/shoucang_xx_red.png b/third/src/main/res/drawable-xhdpi/shoucang_xx_red.png
new file mode 100644
index 0000000..67a5c94
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/shoucang_xx_red.png differ
diff --git a/third/src/main/res/drawable-xhdpi/shouchang_xx.png b/third/src/main/res/drawable-xhdpi/shouchang_xx.png
new file mode 100644
index 0000000..731f423
Binary files /dev/null and b/third/src/main/res/drawable-xhdpi/shouchang_xx.png differ
diff --git a/third/src/main/res/layout/item_share_gridview.xml b/third/src/main/res/layout/item_share_gridview.xml
new file mode 100755
index 0000000..48a6d82
--- /dev/null
+++ b/third/src/main/res/layout/item_share_gridview.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/third/src/main/res/layout/share.xml b/third/src/main/res/layout/share.xml
new file mode 100755
index 0000000..d593b6f
--- /dev/null
+++ b/third/src/main/res/layout/share.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/third/src/main/res/values/colors.xml b/third/src/main/res/values/colors.xml
new file mode 100644
index 0000000..ebf2aa9
--- /dev/null
+++ b/third/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #EFEFEF
+ #E1E1E5
+ #E60012
+
\ No newline at end of file
diff --git a/third/src/main/res/values/strings.xml b/third/src/main/res/values/strings.xml
new file mode 100644
index 0000000..fd3cab4
--- /dev/null
+++ b/third/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+ third
+ 分享成功
+ 取消分享
+ 分享失败
+
diff --git a/third/src/main/res/values/styles.xml b/third/src/main/res/values/styles.xml
new file mode 100644
index 0000000..a9fab6f
--- /dev/null
+++ b/third/src/main/res/values/styles.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
diff --git a/third/src/test/java/com/hd/wlj/third/ExampleUnitTest.java b/third/src/test/java/com/hd/wlj/third/ExampleUnitTest.java
new file mode 100644
index 0000000..66cc6d5
--- /dev/null
+++ b/third/src/test/java/com/hd/wlj/third/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.hd.wlj.third;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file