public class MarkdownView extends WebView {

	private static final String TAG = "MarkdownView";

	public MarkdownView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MarkdownView(Context context) {
		super(context);
	}

	/**
	 * Loads the given Markdown text to the view as rich formatted HTML. The
	 * HTML output will be styled based on the given CSS file.
	 *
	 * @param txt
	 *            - input in markdown format
	 * @param cssFileUrl
	 *            - a URL to css File. If the file located in the project assets
	 *            folder then the URL should start with "file:///android_asset/"
	 */
	public void loadMarkdown(String txt, String cssFileUrl) {
		loadMarkdownToView(txt, cssFileUrl);
	}

	/**
	 * Loads the given Markdown text to the view as rich formatted HTML.
	 *
	 * @param txt
	 *            - input in Markdown format
	 */
	public void loadMarkdown(String txt) {
		loadMarkdown(txt, null);
	}

	/**
	 * Loads the given Markdown file to the view as rich formatted HTML. The HTML
	 * output will be styled based on the given CSS file.
	 *
	 * @param url
	 *            - a URL to the Markdown file. If the file located in the
	 *            project assets folder then the URL should start with
	 *            "file:///android_asset/"
	 * @param cssFileUrl
	 *            - a URL to css File. If the file located in the project assets
	 *            folder then the URL should start with "file:///android_asset/"
	 */
	public void loadMarkdownFile(String url, String cssFileUrl) {
		new LoadMarkdownUrlTask().execute(url, cssFileUrl);
	}

	public void loadMarkdownFile(String url) {
		loadMarkdownFile(url, null);
	}

	private String readFileFromAsset(String fileName){
		try {
			InputStream input =  getContext().getAssets().open(fileName);
			try {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input));
				StringBuilder content = new StringBuilder(input.available());
				String line;
				while ((line = bufferedReader.readLine()) != null) {
					content.append(line);
					content.append(System.getProperty("line.separator"));
				}
				return content.toString();
			} finally { input.close(); }
		} catch (Exception ex){
			Log.d(TAG, "Error while reading file from assets", ex);
			return null;
		}
	}

	private class LoadMarkdownUrlTask extends
			AsyncTask<String, Integer, String> {
		private String cssFileUrl;

		protected String doInBackground(String... params) {
			try {
				String markdown = "";
				String url = params[0];
				this.cssFileUrl = params[1];
				if(URLUtil.isNetworkUrl(url)){
					markdown = HttpHelper.get(url).getResponseMessage();
				} else if (URLUtil.isAssetUrl(url)) {
					markdown = readFileFromAsset(url.substring("file:///android_asset/".length() , url.length()));
				} else{
					throw new IllegalArgumentException("The URL string provided is not a network URL or Asset URL.");
				}

				return markdown;
			} catch (Exception ex) {
				Log.d(TAG, "Error Loading Markdown File.", ex);
				return null;
			}
		}

		protected void onProgressUpdate(Integer... progress) {
			// no-op
		}

		protected void onPostExecute(String result) {
			if (result != null) {
				loadMarkdownToView(result, cssFileUrl);
			} else {
				loadUrl("about:blank");
			}
		}
	}

	private void loadMarkdownToView(String txt, String cssFileUrl) {
		MarkdownProcessor m = new MarkdownProcessor();
		String html = m.markdown(txt);
		if (cssFileUrl != null) {
			html = 	"<link rel='stylesheet' type='text/css' href='"+ cssFileUrl +"' />" + html;
		}
		loadDataWithBaseURL("fake://", html, "text/html", "UTF-8", null);
	}

} public class Article implements Serializable{

    private Long id;
    /** Not-null value. */
    private String date;
    private String address;
    private String weather;
    /** Not-null value. */
    private String title;
    /** Not-null value. */
    private String content;
    private Integer type;
    private String img_path;
    private String objectId;

    // KEEP FIELDS - put your custom fields here
    // KEEP FIELDS END

    public Article() {
    }

    public Article(Long id) {
        this.id = id;
    }

    public Article(Long id, String date, String address, String weather, String title, String content, Integer type, String img_path, String objectId) {
        this.id = id;
        this.date = date;
        this.address = address;
        this.weather = weather;
        this.title = title;
        this.content = content;
        this.type = type;
        this.img_path = img_path;
        this.objectId = objectId;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    /** Not-null value. */
    public String getDate() {
        return date;
    }

    /** Not-null value; ensure this value is available before it is saved to the database. */
    public void setDate(String date) {
        this.date = date;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }

    /** Not-null value. */
    public String getTitle() {
        return title;
    }

    /** Not-null value; ensure this value is available before it is saved to the database. */
    public void setTitle(String title) {
        this.title = title;
    }

    /** Not-null value. */
    public String getContent() {
        return content;
    }

    /** Not-null value; ensure this value is available before it is saved to the database. */
    public void setContent(String content) {
        this.content = content;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public String getImg_path() {
        return img_path;
    }

    public void setImg_path(String img_path) {
        this.img_path = img_path;
    }

    public String getObjectId() {
        return objectId;
    }

    public void setObjectId(String objectId) {
        this.objectId = objectId;
    }

    // KEEP METHODS - put your custom methods here
    // KEEP METHODS END

} public class BaseApplication extends MultiDexApplication {
    public static final String TAG = "BaseApplication";
    /**
     * 全局Context，原理是因为Application类是应用最先运行的，所以在我们的代码调用时，该值已经被赋值过了
     */
    private static BaseApplication mInstance;
    /**
     * 主线程ID
     */
    private static int mMainThreadId = -1;
    /**
     * 主线程ID
     */
    private static Thread mMainThread;
    /**
     * 主线程Handler
     */
    private static Handler mMainThreadHandler;
    /**
     * 主线程Looper
     */
    private static Looper mMainLooper;

    public static Application getInstance() {
        return mInstance;
    }

    private static SQLiteDatabase db;
    private static DaoMaster daoMaster;
    private static DaoSession daoSession;
    private static Picasso picassoSingleton;

    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    @Override
    public void onCreate() {

        super.onCreate();
        initObjects();

        LeakCanary.install(this);
        setUpDataBase();
        createCacheDirectory();

        if (!BuildConfig.DEBUG) {
            LogUtils.mDebuggable = LogUtils.LEVEL_NONE;
        }
        if (checkIfIsAppRunning(getPackageName())) {
            initBuggly();
            initLeanCloud();
        }



    }

    private void initObjects() {
        mInstance = this;
        mMainThreadId = android.os.Process.myTid();
        mMainThread = Thread.currentThread();
        mMainThreadHandler = new Handler();
        mMainLooper = getMainLooper();
        picassoSingleton = Picasso.with(this);
    }

    /**
     * 初始化LeanCloud
     */
    private void initLeanCloud() {
        //如果使用美国节点，请加上这行代码 AVOSCloud.useAVCloudUS();
        AVOSCloud.initialize(this, Constant.LEANCLOUD_APPID, Constant.LEANCLOUD_KEY);
//        AVAnalytics.trackAppOpened(getIntent());
    }

    /**
     * 创建SD卡缓存目录
     */
    private void createCacheDirectory() {
        File imgDirectory = new File(Constant.IMG_CACHE_PATH);
        if(!imgDirectory.exists()){
            imgDirectory.mkdir();
        }
        File articleDirectory = new File(Constant.ARTICLE_CACHE_PATH);
        if(!articleDirectory.exists()){
            articleDirectory.mkdir();
        }
        File reminderDirectory = new File(Constant.REMINDER_CACHE_PATH);
        if(!reminderDirectory.exists()){
            reminderDirectory.mkdir();
        }
    }

    /**
     * 初始化数据库
     */
    private void setUpDataBase() {
        DaoMaster.DevOpenHelper openHelper = new DaoMaster.DevOpenHelper(this, "sxkeji-db", null);
        db = openHelper.getWritableDatabase();
        daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();

    }


    public static Picasso getPicassoSingleton() {
        return picassoSingleton;
    }

    public static SQLiteDatabase getDb() {
        return db;
    }

    public static DaoMaster getDaoMaster() {
        return daoMaster;
    }

    public static DaoSession getDaoSession() {
        return daoSession;
    }


    /**
     * 初始化buggly
     */
    private void initBuggly() {
        //TODO 设置Buggly 渠道 和 App的版本
//        CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(this);
//        strategy.setAppChannel(AppUtils.getAppChannel(this));
//        strategy.setAppVersion(AppUtils.getVersionName(this));
//        CrashReport.initCrashReport(this, "900010286", BuildConfig.DEBUG, strategy);
//
//        setUncaughtExcept();//全局捕获异常

    }


    private void setUncaughtExcept() {
        Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {
                try {
                    StringWriter sw = new StringWriter();
                    PrintWriter pw = new PrintWriter(sw);

                    Field[] fileds = Build.class.getDeclaredFields();
                    for (Field filed : fileds) {

                        sw.write(filed.getName() + "--" + filed.get(null) + "\n");
                    }
                    ex.printStackTrace(pw);
                    File file = new File(Environment.getExternalStorageDirectory(), "log.txt");
                    FileOutputStream fos = new FileOutputStream(file);
                    fos.write(sw.toString().getBytes());
                    fos.close();
                    pw.close();
                    sw.close();

                    android.os.Process.killProcess(android.os.Process.myPid());

                } catch (Exception e) {
                    android.os.Process.killProcess(android.os.Process.myPid());
                    e.printStackTrace();
                }
            }
        });

    }


    public static BaseApplication getApplication() {
        return mInstance;
    }

    /**
     * 获取主线程ID
     */
    public static int getMainThreadId() {
        return mMainThreadId;
    }

    /**
     * 获取主线程
     */
    public static Thread getMainThread() {
        return mMainThread;
    }

    /**
     * 获取主线程的handler
     */
    public static Handler getMainThreadHandler() {
        return mMainThreadHandler;
    }

    /**
     * 获取主线程的looper
     */
    public static Looper getMainThreadLooper() {
        return mMainLooper;
    }

    /**
     * volley 请求对列
     *
     * @return
     */


    /**
     * 判断程序是否运行
     *
     * @param processName
     * @return
     */
    private boolean checkIfIsAppRunning(String processName) {
        int pid = android.os.Process.myPid();
        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningAppProcessInfo> mRunningList = am.getRunningAppProcesses();
        Iterator<RunningAppProcessInfo> iterator = mRunningList.iterator();
        while (iterator.hasNext()) {
            RunningAppProcessInfo info = (RunningAppProcessInfo) iterator.next();
            if (info.pid == pid) {
                if (processName.equals(info.processName)) {
                    return true;
                }
            }
        }
        return false;
    }
}
 public class HttpClient {
    static volatile HttpClient singleton = null;
    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
    private String UTF_8 = "UTF-8";
    private MediaType MEDIA_TYPE = MediaType.parse("text/plain;");
    private OkHttpClient client = new OkHttpClient();
    private boolean isShowProgressDialog = true;
    private Context context;
    private Dialog dialog;
    private LoadingPage loadingPage;
    private View successedView;


    public HttpClient(Context context) {
        this.context = context;
        client.setConnectTimeout(30, TimeUnit.SECONDS);
        initDialog();

    }

    private void initDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.progressDialog);
        dialog = builder.create();
        dialog.setCancelable(false);
    }

    private void dialogShow() {
        dialog.show();
        dialog.getWindow().setContentView(R.layout.loading_view);
        dialog.findViewById(R.id.loadviewLinear).setVisibility(View.VISIBLE);
    }

    private void dialogCancle() {
        dialog.cancel();
    }

    public static HttpClient builder(Context context) {
//        if (singleton == null) {
//            synchronized (HttpClient.class) {
//                if (singleton == null) {
//                    singleton = new HttpClient(context);
//                }
//            }
//        }
        synchronized (HttpClient.class) {
            singleton = new HttpClient(context);
        }
        return singleton;
    }

    /*
    * 控制ProgressDialog的显示 默认是显示的，设置isShow为false 可以取消显示
    * */
    public HttpClient showProgress(boolean isShow) {
        this.isShowProgressDialog = isShow;
        return this;
    }

    /***
     * loadPage  就是LoadingPage
     * successedView 就是成功显示界面
     */
    public HttpClient setLoadingPage(LoadingPage loadPage, View successedView) {
        this.loadingPage = loadPage;
        this.successedView = successedView;
        this.isShowProgressDialog = false;
        return this;
    }

    public boolean isNetworkAvailable(Context context) {
        try {
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
            return networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected();
        } catch (Exception e) {
            Log.v("ConnectivityManager", e.getMessage());
        }
        return false;
    }

    public void get(String url, Map<String, String> map, final HttpResponseHandler httpResponseHandler) {
        if (NetWorkUtils.isNetworkAvailable(context)) {


            if (isShowProgressDialog) {
                dialogShow();
            }
            url = url + "?" + mapUrl(map);
            LogUtils.e("url++++++++++++" + url);
            httpResponseHandler.setLoadingPage(loadingPage, successedView);
            Request request = new Request.Builder().url(url).build();
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onResponse(Response response) throws IOException {
                    if (isShowProgressDialog) {
                        dialogCancle();
                    }
                    httpResponseHandler.sendSuccessMessage(response);
                }

                @Override
                public void onFailure(Request request, IOException e) {
                    if (isShowProgressDialog) {
                        dialogCancle();
                    }
                    httpResponseHandler.sendFailureMessage(request, e);
                }
            });
        } else {

            if (null != loadingPage) {
                loadingPage.setmState(LoadingPage.STATE_NONETWORK);
                loadingPage.showPage();
            } else {
                UIUtils.showToastSafe(context, UIUtils.getString(context, R.string.network_no));
            }
        }
    }

    public void post(String url, Map<String, String> map, final HttpResponseHandler httpResponseHandler) {
        if (NetWorkUtils.isNetworkAvailable(context)) {


            if (isShowProgressDialog) {
                dialogShow();
            }
            LogUtils.e("url++++++" + url);


            httpResponseHandler.setLoadingPage(loadingPage, successedView);
            FormEncodingBuilder builder = new FormEncodingBuilder();
            mapBuilder(map, builder);
            Request request = new Request.Builder().url(url).post(builder.build()).build();
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onResponse(Response response) {
                    if (isShowProgressDialog) {
                        dialogCancle();
                    }
                    httpResponseHandler.sendSuccessMessage(response);
                }

                @Override
                public void onFailure(Request request, IOException e) {
                    if (isShowProgressDialog) {
                        dialogCancle();
                    }
                    httpResponseHandler.sendFailureMessage(request, e);
                }
            });
        } else {

            if (null != loadingPage) {
                loadingPage.setmState(LoadingPage.STATE_NONETWORK);
                loadingPage.showPage();
            } else {
                UIUtils.showToastSafe(context, UIUtils.getString(context, R.string.network_no));
            }

        }

    }

    public void postImage(String url, Map<String, String> map, final HttpResponseHandler httpResponseHandler, UIProgressListener uiProgressRequestListener) {
        RequestBody requestBody = null;
        if (NetWorkUtils.isNetworkAvailable(context)) {


            if (isShowProgressDialog) {
                dialogShow();
            }


            File uploadFile = new File(map.get("imageFile"));
            requestBody = new MultipartBuilder().type(MultipartBuilder.FORM)
                    .addFormDataPart("moduleName", map.get("moduleName"))
                    .addFormDataPart("token", map.get("token"))
                    .addFormDataPart("clientVersion", "1.0.0")

                    .addFormDataPart("imageFile", "image.png", RequestBody.create(MEDIA_TYPE_PNG, uploadFile))

                    .build();


            Request request = new Request.Builder()
                    .url(url)
//                .addHeader("Content-Type", "multipart/form-data;boundary=" + BOUNDARY)
                    .post(ProgressHelper.addProgressRequestListener(requestBody, uiProgressRequestListener))
                    .build();


            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onResponse(Response response) {
                    if (isShowProgressDialog) {
                        dialogCancle();
                    }
                    httpResponseHandler.sendSuccessMessage(response);
                }

                @Override
                public void onFailure(Request request, IOException e) {
                    if (isShowProgressDialog) {
                        dialogCancle();
                    }
                    httpResponseHandler.sendFailureMessage(request, e);
                }
            });
        } else {

            if (null != loadingPage) {
                loadingPage.setmState(LoadingPage.STATE_NONETWORK);
                loadingPage.showPage();
            } else {
                UIUtils.showToastSafe(context, UIUtils.getString(context, R.string.network_no));
            }

        }

    }


    private void mapBuilder(Map<String, String> map, FormEncodingBuilder builder) {
        for (Map.Entry<String, String> entry : map.entrySet()) {
            builder.add(entry.getKey(), entry.getValue());
            LogUtils.e("m.getKey()+++++" + entry.getKey() + " " + entry.getValue());
        }
    }

    private String mapUrl(Map<String, String> map) {
        StringBuffer buffer = new StringBuffer();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            buffer.append(entry.getKey());
            buffer.append("=");
            buffer.append(entry.getValue());
            buffer.append("&");
        }
        buffer.setLength(buffer.length() - 1);
        return buffer.toString();
    }

    /**
     * 上传Article到LeanCloud
     *
     * @param article
     */
    public static void uploadArticle2LeanCloud(final Context context, Article article) {
        String userNumber = (String) SharedPreferencesUtils.get(context, Constant.ACCOUNT_USER_NUMBER, "");
        if (TextUtils.isEmpty(userNumber)) {
            LogUtils.e("upload2LeanCloud", "userNumber is null , upload failed!");
            return;
        }
        AVObject uploadArticle = new AVObject(Constant.LEANCLOUD_TABLE_DIARY);
        uploadArticle.put("address", article.getAddress());
        uploadArticle.put("weather", article.getWeather());
        uploadArticle.put("title", article.getTitle());
        uploadArticle.put("content", article.getContent());
        uploadArticle.put("type", article.getType());
        uploadArticle.put("img_path", article.getImg_path());
        uploadArticle.put(Constant.LEANCLOUD_TABLE_USERNUMBER, userNumber);

        uploadArticle.saveInBackground(new SaveCallback() {
            @Override
            public void done(AVException e) {
                if (e == null) {
                    UIUtils.showToastSafe(context, "上传云端成功");
                } else {
                    UIUtils.showToastSafe(context, "上传云端失败" + e.getMessage());
//                    LogUtils.e("upload2LeanCloud", "LeanCloud save result : " + e.getMessage());
                }
            }
        });
    }

    /**
     * 上传ToDo到云端
     *
     * @param context
     * @param todo
     */
    public static AVObject uploadTodo2Cloud(final Context context, Todo todo) {
        String userNumber = (String) SharedPreferencesUtils.get(context, Constant.ACCOUNT_USER_NUMBER, "");
        if (TextUtils.isEmpty(userNumber)) {
            LogUtils.e("uploadTodo2Cloud", "userNumber is null , upload failed!");
            return null;
        }
        String objectId = todo.getObjectId();

        AVObject uploadTodo = new AVObject(Constant.LEANCLOUD_TABLE_TODO);
        if (!TextUtils.isEmpty(objectId)){
            uploadTodo.put("objectId", objectId);
        }
        uploadTodo.put(Constant.LEANCLOUD_TABLE_USERNUMBER, userNumber);
        uploadTodo.put("date", todo.getDate());
        //TODO:到底要不要内容呢？还是只一个标题就好了,在"一起改进"里问一下
        uploadTodo.put("title", todo.getContent());
        uploadTodo.put("color", todo.getColor());
        uploadTodo.put("isFinished", false);
        uploadTodo.put("hasReminder", todo.getHasReminder());
        uploadTodo.put("showOnLockScreen", todo.getShowOnLockScreen());

        uploadTodo.saveInBackground(new SaveCallback() {
            @Override
            public void done(AVException e) {
                if (e == null) {
                    UIUtils.showToastSafe(context, "上传云端成功");
                } else {
                    UIUtils.showToastSafe(context, "上传云端失败" + e.getMessage());
//                    LogUtils.e("upload2LeanCloud", "LeanCloud save result : " + e.getMessage());
                }
            }
        });
        return uploadTodo;
    }
} public class Constant {
    //常量
    public static String appName = "365_diary";
    public static String showGuide = "show_guide";
    public static int SPLASH_DELAYED_TIME = 3000;
    public static String ARTICLE_BEAN = "article_bean";
    public static String ARTICLE_TYPE = "article_type";
    public static String OPEN_EYE_DATA = "open_eye_dialy";
    public static final String GESTURE_PASSWORD = "GesturePassword";
    public static final String THEME = "theme";
    public static final String THEME_LIGHT = "theme_light";
    public static final String THEME_DARK = "theme_dark";

    //账户状态相关
    public static final String ACCOUNT_IS_LOGIN = "account_login";
    public static final String ACCOUNT_USER_NUMBER = "account_number";

    //可以用户设置的状态
    public static final String SETTING_TODO_ORDER = "todo_order";
    public static final String SETTING_TODO_AUTO_SYNC = "todo_auto_sync";       //保存后自动上传

    //Activity间跳转传递的数据
    public static final String EXTRA_FROM = "start_from";
    public static final String EXTRA_TO = "jump_to";
    public static final String ACTIVITY_CLOUD_BACK = "activity_cloud_back";
    public static final String ACTIVITY_LOCAL_EXPROT = "activity_local_export";
    public static final String ACTIVITY_SETTING = "activity_setting";
    public static final String PLAY_TITLE = "play_title";
    public static final String PLAY_URL = "play_url";
    public static final String EXTRA_TODO = "todo";

    //LeanCloud ID 和 Key
    public static String LEANCLOUD_APPID = "p5u1dmlmaznldib4hu0goexf4cg5kwwed7to6pdhsm9x8dpd";
    public static String LEANCLOUD_KEY = "3qd9nuefo4fyzknx3cwk15mvgwoctym1l3ohb1ndhk5xfl3y";
    //LeanCloud 表名、字段名
    public static String LEANCLOUD_TABLE_DIARY = "articles_365";
    public static String LEANCLOUD_TABLE_TODO = "todo_365";
    public static String LEANCLOUD_TABLE_USERNUMBER = "user_number";
    //Article 字段名
    public static String LEANCLOUD_ARTICLE_PROPERTY_DATE = "date";
    public static String LEANCLOUD_ARTICLE_PROPERTY_ADDRESS = "address";
    public static String LEANCLOUD_ARTICLE_PROPERTY_WEATHER = "weather";
    public static String LEANCLOUD_ARTICLE_PROPERTY_TITLE = "title";
    public static String LEANCLOUD_ARTICLE_PROPERTY_CONTENT = "content";
    public static String LEANCLOUD_ARTICLE_PROPERTY_TYPE = "type";
    public static String LEANCLOUD_ARTICLE_PROPERTY_IMGPATH = "img_path";
    public static String LEANCLOUD_ARTICLE_PROPERTY_OBJECTID = "objectId";

    //To do 字段名
    public static String LEANCLOUD_TODO_PROPERTY_DATE = "date";
    public static String LEANCLOUD_TODO_PROPERTY_TITLE = "title";
    public static String LEANCLOUD_TODO_PROPERTY_COLOR = "color";
    public static String LEANCLOUD_TODO_PROPERTY_ISFINISHED = "isFinished";
    public static String LEANCLOUD_TODO_PROPERTY_REMINDER = "hasReminder";
    public static String LEANCLOUD_TODO_PROPERTY_SHOW_ON_SCREEN = "showOnLockScreen";
    public static String LEANCLOUD_TODO_PROPERTY_OBJECTID = "objectId";

    public static final String OPEN_EYE_UID = "57e17df8bc634de8b5d427bd27a126b9f1ba1a56";
    //    vc=74&vn=1.10.1&deviceModel=m1%20note&first_channel=eyepetizer_meizu_market&last_channel=eyepetizer_meizu_market%20ZHOU
    public static final String OPEN_EYE_VC = "74";
    public static final String OPEN_EYE_VN = "1.10.1";
    public static final String OPEN_EYE_DEVICEMODEL = "m1%20note";
    public static final String OPEN_EYE_FIRST_CHANNEL = "eyepetizer_meizu_market";
    public static final String OPEN_EYE_LAST_CHANNEL = "eyepetizer_meizu_market%20ZHOU";

    //文档类型
    public static final int TYPE_MARKDOWN = 0 ; //markdown
    public static final int TYPE_NORMAL = 1 ;
    public static final int TYPE_REMINDER = 2;  //to do
    public static final int TYPE_DRAFT = 3 ; //草稿

    //缓存相关
    public static final String LAST_UPDATE_IMG = "last_update_img";
    public static final String LAST_UPDATE_OPEN_EYE = "last_update_eye";
    public static final String LAST_SYNC_TIME = "last_sync_time";

    //缓存地址
    public static final String BASE_CACHE_FILE_PATH = "sdcard/sxkeji/";
    public static final String IMG_CACHE_PATH = BASE_CACHE_FILE_PATH + "images/";
    public static final String ARTICLE_CACHE_PATH = BASE_CACHE_FILE_PATH + "articles/";
    public static final String REMINDER_CACHE_PATH = BASE_CACHE_FILE_PATH + "reminds/";

    //接口地址
    //文字配图网络地址，返回的就是图片
    public static final String URL_IMG = "http://tu.ihuan.me/tu/api/me_all_pic/";
    //豆瓣电影top250 https://api.douban.com/v2/movie/top250?start=0&count=10
    public static final String URL_DOUBAN_MOVIE_TOP250 = "https://api.douban.com/v2/movie/";
    //开眼每周API http://baobab.wandoujia.com/api/v3/ranklist?num=100&strategy=weekly&udid=57e17df8bc634de8b5d427bd27a126b9f1ba1a56&vc=74&vn=1.10.1&deviceModel=m1%20note&first_channel=eyepetizer_meizu_market&last_channel=eyepetizer_meizu_market%20ZONG
    public static final String URL_OPEN_EYE_WEEKLY = "http://baobab.wandoujia.com/api/v3/ranklist";
     //开眼每日API  http://baobab.wandoujia.com/api/v2/feed?num=2&udid=57e17df8bc634de8b5d427bd27a126b9f1ba1a56&vc=74&vn=1.10.1&deviceModel=m1%20note&first_channel=eyepetizer_meizu_market&last_channel=eyepetizer_meizu_market%20ZHOU
    public static final String URL_OPEN_EYE_DIALY = "http://baobab.wandoujia.com/api/v2/feed";
}
 public class SharedPreferencesUtils {
    /**
     * 保存在手机里面的文件名
     */
    public static final String FILE_NAME = "ymc_sp";

    /**
     * 保存数据的方法，我们需要拿到保存数据的具体类型，然后根据类型调用不同的保存方法
     *
     * @param context
     * @param key
     * @param object
     */
    public static void put(Context context, String key, Object object)
    {

        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();

        if (object instanceof String)
        {
            editor.putString(key, (String) object);
        } else if (object instanceof Integer)
        {
            editor.putInt(key, (Integer) object);
        } else if (object instanceof Boolean)
        {
            editor.putBoolean(key, (Boolean) object);
        } else if (object instanceof Float)
        {
            editor.putFloat(key, (Float) object);
        } else if (object instanceof Long)
        {
            editor.putLong(key, (Long) object);
        } else
        {
            editor.putString(key, object.toString());
        }

        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 得到保存数据的方法，我们根据默认值得到保存的数据的具体类型，然后调用相对于的方法获取值
     *
     * @param context
     * @param key
     * @param defaultObject can not be null !!!
     * @return
     */
    public static Object get(Context context, String key, Object defaultObject)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);

        if (defaultObject instanceof String)
        {
            return sp.getString(key, (String) defaultObject);
        } else if (defaultObject instanceof Integer)
        {
            return sp.getInt(key, (Integer) defaultObject);
        } else if (defaultObject instanceof Boolean)
        {
            return sp.getBoolean(key, (Boolean) defaultObject);
        } else if (defaultObject instanceof Float)
        {
            return sp.getFloat(key, (Float) defaultObject);
        } else if (defaultObject instanceof Long)
        {
            return sp.getLong(key, (Long) defaultObject);
        }

        return null;
    }

    /**
     * 移除某个key值已经对应的值
     * @param context
     * @param key
     */
    public static void remove(Context context, String key)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 清除所有数据
     * @param context
     */
    public static void clear(Context context)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 查询某个key是否已经存在
     * @param context
     * @param key
     * @return
     */
    public static boolean contains(Context context, String key)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        return sp.contains(key);
    }

    /**
     * 返回所有的键值对
     *
     * @param context
     * @return
     */
    public static Map<String, ?> getAll(Context context)
    {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        return sp.getAll();
    }

    /**
     * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
     *
     * @author zhy
     *
     */
    private static class SharedPreferencesCompat
    {
        private static final Method sApplyMethod = findApplyMethod();

        /**
         * 反射查找apply的方法
         *
         * @return
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        private static Method findApplyMethod()
        {
            try
            {
                Class clz = SharedPreferences.Editor.class;
                return clz.getMethod("apply");
            } catch (NoSuchMethodException e)
            {
            }

            return null;
        }

        /**
         * 如果找到则使用apply执行，否则使用commit
         *
         * @param editor
         */
        public static void apply(SharedPreferences.Editor editor)
        {
            try
            {
                if (sApplyMethod != null)
                {
                    sApplyMethod.invoke(editor);
                    return;
                }
            } catch (IllegalArgumentException e)
            {
            } catch (IllegalAccessException e)
            {
            } catch (InvocationTargetException e)
            {
            }
            editor.commit();
        }
    }
} public class FileUtils {
    public static final String ROOT_DIR = Constant.appName;
    public static final String DOWNLOAD_DIR = "download";
    public static final String CACHE_DIR = "cache";
    public static final String EXPORT_DIR = "export";    //导出文件夹
    public static final String ICON_DIR = "icon";
    public static final String IMG_DIR = "image";

    /**
     * 判断SD卡是否挂载
     */
    public static boolean isSDCardAvailable() {
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取下载目录
     */
    public static String getDownloadDir(Context context) {
        return getDir(context, DOWNLOAD_DIR);
    }

    /**
     * 获取缓存目录
     */
    public static String getCacheDir(Context context) {
        return getDir(context, CACHE_DIR);
    }

    /**
     * 获取导出文件夹的目录
     */
    public static String getExportDir(Context context) {
        return getDir(context, EXPORT_DIR);
    }

    /**
     * 获取icon目录
     */
    public static String getIconDir(Context context) {
        return getDir(context, ICON_DIR);
    }

    /**
     * 获取img目录
     */
    public static String getImgDir(Context context) {
        return getDir(context, IMG_DIR);
    }

    /**
     * 获取最新缓存的图片
     *
     * @param context
     * @return
     */
    public static File getLatestSaveImgFilr(Context context) {
        File mLatestImge = null;
        File ImgPath = new File(getImgDir(context));
        if (ImgPath.isDirectory()) {
            File[] files = ImgPath.listFiles();
            if (files.length > 1) {
                mLatestImge = files[files.length - 1];//加载倒数第二张
                Log.e("FileUtils", "getLatestSaveImgFilr" + mLatestImge.getName());
            }
        } else {
            Log.e("FileUtils", "getLatestSaveImgFilr" + ImgPath.getName());
        }
        return mLatestImge;
    }

    /**
     * 使用Picasso缓存图片到指定地点
     *
     * @param context
     */
    public static Target getDownloadTarget(final Context context) {
        Target saveTarget;
        saveTarget = new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                String imgName = System.currentTimeMillis() + ".png";
                File downloadFile = new File(getImgDir(context), imgName);
//                File downloadFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
//                        + File.separator, "sxkeji/");
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(downloadFile);
                    bitmap = ThumbnailUtils.extractThumbnail(bitmap, 820, 480);
                    bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
                    fos.flush();
                    fos.close();
//					showToast("图片下载至 " + downloadFile.getPath());
                    Log.e("downloadImg", "图片下载至 " + downloadFile.getPath());
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    Log.e("saveTarget", e.toString());
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("saveTarget", e.toString());
                }

            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {

            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {

            }
        };
        return saveTarget;
    }


    /**
     * 获取应用目录，当SD卡存在时，获取SD卡上的目录，当SD卡不存在时，获取应用的cache目录
     */
    public static String getDir(Context context, String name) {
        StringBuilder sb = new StringBuilder();
        if (isSDCardAvailable()) {
            sb.append(getExternalStoragePath());
        } else {
            sb.append(getCachePath(context));
        }
        sb.append(name);
        sb.append(File.separator);
        String path = sb.toString();
        if (createDirs(path)) {
            return path;
        } else {
            return null;
        }
    }

    /**
     * 获取SD下的应用目录
     */
    public static String getExternalStoragePath() {
        StringBuilder sb = new StringBuilder();
        sb.append(Environment.getExternalStorageDirectory().getAbsolutePath());
        sb.append(File.separator);
        sb.append(ROOT_DIR);
        sb.append(File.separator);
        return sb.toString();
    }

    /**
     * 获取应用的cache目录
     */
    public static String getCachePath(Context context) {
        File f = context.getCacheDir();
        if (null == f) {
            return null;
        } else {
            return f.getAbsolutePath() + "/";
        }
    }

    /**
     * 创建文件夹
     */
    public static boolean createDirs(String dirPath) {
        File file = new File(dirPath);
        if (!file.exists() || !file.isDirectory()) {
            return file.mkdirs();
        }
        return true;
    }

    /**
     * 复制文件，可以选择是否删除源文件
     */
    public static boolean copyFile(String srcPath, String destPath, boolean deleteSrc) {
        File srcFile = new File(srcPath);
        File destFile = new File(destPath);
        return copyFile(srcFile, destFile, deleteSrc);
    }

    /**
     * 复制文件，可以选择是否删除源文件
     */
    public static boolean copyFile(File srcFile, File destFile, boolean deleteSrc) {
        if (!srcFile.exists() || !srcFile.isFile()) {
            return false;
        }
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(destFile);
            byte[] buffer = new byte[1024];
            int i = -1;
            while ((i = in.read(buffer)) > 0) {
                out.write(buffer, 0, i);
                out.flush();
            }
            if (deleteSrc) {
                srcFile.delete();
            }
        } catch (Exception e) {
            LogUtils.e(e);
            return false;
        } finally {
            IOUtils.close(out);
            IOUtils.close(in);
        }
        return true;
    }

    /**
     * 判断文件是否可写
     */
    public static boolean isWriteable(String path) {
        try {
            if (StringUtils.isEmpty(path)) {
                return false;
            }
            File f = new File(path);
            return f.exists() && f.canWrite();
        } catch (Exception e) {
            LogUtils.e(e);
            return false;
        }
    }

    /**
     * 修改文件的权限,例如"777"等
     */
    public static void chmod(String path, String mode) {
        try {
            String command = "chmod " + mode + " " + path;
            Runtime runtime = Runtime.getRuntime();
            runtime.exec(command);
        } catch (Exception e) {
            LogUtils.e(e);
        }
    }

    /**
     * 把数据写入文件
     *
     * @param is       数据流
     * @param path     文件路径
     * @param recreate 如果文件存在，是否需要删除重建
     * @return 是否写入成功
     */
    public static boolean writeFile(InputStream is, String path, boolean recreate) {
        boolean res = false;
        File f = new File(path);
        FileOutputStream fos = null;
        try {
            if (recreate && f.exists()) {
                f.delete();
            }
            if (!f.exists() && null != is) {
                File parentFile = new File(f.getParent());
                parentFile.mkdirs();
                int count = -1;
                byte[] buffer = new byte[1024];
                fos = new FileOutputStream(f);
                while ((count = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, count);
                }
                res = true;
            }
        } catch (Exception e) {
            LogUtils.e(e);
        } finally {
            IOUtils.close(fos);
            IOUtils.close(is);
        }
        return res;
    }

    /**
     * 把字符串数据写入文件
     *
     * @param content 需要写入的字符串
     * @param path    文件路径名称
     * @param append  是否以添加的模式写入
     * @return 是否写入成功
     */
    public static boolean writeFile(byte[] content, String path, boolean append) {
        boolean res = false;
        File f = new File(path);
        RandomAccessFile raf = null;
        try {
            if (f.exists()) {
                if (!append) {
                    f.delete();
                    f.createNewFile();
                }
            } else {
                f.createNewFile();
            }
            if (f.canWrite()) {
                raf = new RandomAccessFile(f, "rw");
                raf.seek(raf.length());
                raf.write(content);
                res = true;
            }
        } catch (Exception e) {
            LogUtils.e(e);
        } finally {
            IOUtils.close(raf);
        }
        return res;
    }

    /**
     * 把字符串数据写入文件
     *
     * @param content 需要写入的字符串
     * @param path    文件路径名称
     * @param append  是否以添加的模式写入
     * @return 是否写入成功
     */
    public static boolean writeFile(String content, String path, boolean append) {
        return writeFile(content.getBytes(), path, append);
    }

    /**
     * 把键值对写入文件
     *
     * @param filePath 文件路径
     * @param key      键
     * @param value    值
     * @param comment  该键值对的注释
     */
    public static void writeProperties(String filePath, String key, String value, String comment) {
        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(filePath)) {
            return;
        }
        FileInputStream fis = null;
        FileOutputStream fos = null;
        File f = new File(filePath);
        try {
            if (!f.exists() || !f.isFile()) {
                f.createNewFile();
            }
            fis = new FileInputStream(f);
            Properties p = new Properties();
            p.load(fis);// 先读取文件，再把键值对追加到后面
            p.setProperty(key, value);
            fos = new FileOutputStream(f);
            p.store(fos, comment);
        } catch (Exception e) {
            LogUtils.e(e);
        } finally {
            IOUtils.close(fis);
            IOUtils.close(fos);
        }
    }

    /**
     * 根据值读取
     */
    public static String readProperties(String filePath, String key, String defaultValue) {
        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(filePath)) {
            return null;
        }
        String value = null;
        FileInputStream fis = null;
        File f = new File(filePath);
        try {
            if (!f.exists() || !f.isFile()) {
                f.createNewFile();
            }
            fis = new FileInputStream(f);
            Properties p = new Properties();
            p.load(fis);
            value = p.getProperty(key, defaultValue);
        } catch (IOException e) {
            LogUtils.e(e);
        } finally {
            IOUtils.close(fis);
        }
        return value;
    }

    /**
     * 把字符串键值对的map写入文件
     */
    public static void writeMap(String filePath, Map<String, String> map, boolean append, String comment) {
        if (map == null || map.size() == 0 || StringUtils.isEmpty(filePath)) {
            return;
        }
        FileInputStream fis = null;
        FileOutputStream fos = null;
        File f = new File(filePath);
        try {
            if (!f.exists() || !f.isFile()) {
                f.createNewFile();
            }
            Properties p = new Properties();
            if (append) {
                fis = new FileInputStream(f);
                p.load(fis);// 先读取文件，再把键值对追加到后面
            }
            p.putAll(map);
            fos = new FileOutputStream(f);
            p.store(fos, comment);
        } catch (Exception e) {
            LogUtils.e(e);
        } finally {
            IOUtils.close(fis);
            IOUtils.close(fos);
        }
    }

    /**
     * 把字符串键值对的文件读入map
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static Map<String, String> readMap(String filePath, String defaultValue) {
        if (StringUtils.isEmpty(filePath)) {
            return null;
        }
        Map<String, String> map = null;
        FileInputStream fis = null;
        File f = new File(filePath);
        try {
            if (!f.exists() || !f.isFile()) {
                f.createNewFile();
            }
            fis = new FileInputStream(f);
            Properties p = new Properties();
            p.load(fis);
            map = new HashMap<String, String>((Map) p);// 因为properties继承了map，所以直接通过p来构造一个map
        } catch (Exception e) {
            LogUtils.e(e);
        } finally {
            IOUtils.close(fis);
        }
        return map;
    }

    /**
     * 改名
     */
    public static boolean copy(String src, String des, boolean delete) {
        File file = new File(src);
        if (!file.exists()) {
            return false;
        }
        File desFile = new File(des);
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream(file);
            out = new FileOutputStream(desFile);
            byte[] buffer = new byte[1024];
            int count = -1;
            while ((count = in.read(buffer)) != -1) {
                out.write(buffer, 0, count);
                out.flush();
            }
        } catch (Exception e) {
            LogUtils.e(e);
            return false;
        } finally {
            IOUtils.close(in);
            IOUtils.close(out);
        }
        if (delete) {
            file.delete();
        }
        return true;
    }
}
 public class LogUtils {
    /**
     * 日志输出级别NONE
     */
    public static final int LEVEL_NONE = 0;
    /**
     * 日志输出级别V
     */
    public static final int LEVEL_VERBOSE = 1;
    /**
     * 日志输出级别D
     */
    public static final int LEVEL_DEBUG = 2;
    /**
     * 日志输出级别I
     */
    public static final int LEVEL_INFO = 3;
    /**
     * 日志输出级别W
     */
    public static final int LEVEL_WARN = 4;
    /**
     * 日志输出级别E
     */
    public static final int LEVEL_ERROR = 5;

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

    /**
     * 用于记时的变量
     */
    private static long mTimestamp = 0;
    /**
     * 写文件的锁对象
     */
    private static final Object mLogLock = new Object();

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

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

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

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

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

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

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

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

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

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

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

    /**
     * 把Log存储到文件中
     *
     * @param log  需要存储的日志
     * @param path 存储路径
     */
    public static void log2File(String log, String path) {
        log2File(log, path, true);
    }

    public static void log2File(String log, String path, boolean append) {
        synchronized (mLogLock) {
            FileUtils.writeFile(log + "\r\n", path, append);
        }
    }

    /**
     * 以级别为 e 的形式输出msg信息,附带时间戳，用于输出一个时间段起始点
     *
     * @param msg 需要输出的msg
     */
    public static void msgStartTime(String msg) {
        mTimestamp = System.currentTimeMillis();
        if (!TextUtils.isEmpty(msg)) {
            e("[Started：" + mTimestamp + "]" + msg);
        }
    }

    /**
     * 以级别为 e 的形式输出msg信息,附带时间戳，用于输出一个时间段结束点* @param msg 需要输出的msg
     */
    public static void elapsed(String msg) {
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - mTimestamp;
        mTimestamp = currentTime;
        e("[Elapsed：" + elapsedTime + "]" + msg);
    }

    public static <T> void printList(List<T> list) {
        if (list == null || list.size() < 1) {
            return;
        }
        int size = list.size();
        i("---begin---");
        for (int i = 0; i < size; i++) {
            i(i + ":" + list.get(i).toString());
        }
        i("---end---");
    }

    public static <T> void printArray(T[] array) {
        if (array == null || array.length < 1) {
            return;
        }
        int length = array.length;
        i("---begin---");
        for (int i = 0; i < length; i++) {
            i(i + ":" + array[i].toString());
        }
        i("---end---");
    }


}
 public class NetWorkUtils {

    public static final String NETWORK_TYPE_WIFI = "wifi";
    public static final String NETWORK_TYPE_3G = "3g";
    public static final String NETWORK_TYPE_2G = "2g";
    public static final String NETWORK_TYPE_WAP = "wap";
    public static final String NETWORK_TYPE_UNKNOWN = "unknown";
    public static final String NETWORK_TYPE_DISCONNECT = "disconnect";

    /**
     * Get network type
     *
     * @param context
     * @return boolean
     */
    public static int getNetworkType(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager == null ? null : connectivityManager.getActiveNetworkInfo();
        return networkInfo == null ? -1 : networkInfo.getType();
    }

    /**
     * Get network type name
     *
     * @param context
     * @return boolean
     */
    public static String getNetworkTypeName(Context context) {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo;
        String type = NETWORK_TYPE_DISCONNECT;
        if (manager == null || (networkInfo = manager.getActiveNetworkInfo()) == null) {
            return type;
        }
        ;

        if (networkInfo.isConnected()) {
            String typeName = networkInfo.getTypeName();
            if ("WIFI".equalsIgnoreCase(typeName)) {
                type = NETWORK_TYPE_WIFI;
            } else if ("MOBILE".equalsIgnoreCase(typeName)) {
                String proxyHost = android.net.Proxy.getDefaultHost();
                type = TextUtils.isEmpty(proxyHost) ? (isFastMobileNetwork(context) ? NETWORK_TYPE_3G : NETWORK_TYPE_2G)
                        : NETWORK_TYPE_WAP;
            } else {
                type = NETWORK_TYPE_UNKNOWN;
            }
        }
        return type;
    }

    /**
     * 描述：判断网络是否有效.
     *
     * @param context the context
     * @return true, if is network available
     */
    public static boolean isNetworkAvailable(Context context) {
        if(context == null)
            return false;
        try {
            ConnectivityManager connectivity = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            if (connectivity != null) {
                NetworkInfo info = connectivity.getActiveNetworkInfo();
                if (info != null && info.isConnected()) {
                    if (info.getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    /**
     * Whether is fast mobile network
     *
     * @param context
     * @return boolean
     */

    private static boolean isFastMobileNetwork(Context context) {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (telephonyManager == null) {
            return false;
        }

        switch (telephonyManager.getNetworkType()) {
            case TelephonyManager.NETWORK_TYPE_1xRTT:
                return false;
            case TelephonyManager.NETWORK_TYPE_CDMA:
                return false;
            case TelephonyManager.NETWORK_TYPE_EDGE:
                return false;
            case TelephonyManager.NETWORK_TYPE_EVDO_0:
                return true;
            case TelephonyManager.NETWORK_TYPE_EVDO_A:
                return true;
            case TelephonyManager.NETWORK_TYPE_GPRS:
                return false;
            case TelephonyManager.NETWORK_TYPE_HSDPA:
                return true;
            case TelephonyManager.NETWORK_TYPE_HSPA:
                return true;
            case TelephonyManager.NETWORK_TYPE_HSUPA:
                return true;
            case TelephonyManager.NETWORK_TYPE_UMTS:
                return true;
            case TelephonyManager.NETWORK_TYPE_EHRPD:
                return true;
            case TelephonyManager.NETWORK_TYPE_EVDO_B:
                return true;
            case TelephonyManager.NETWORK_TYPE_HSPAP:
                return true;
            case TelephonyManager.NETWORK_TYPE_IDEN:
                return false;
            case TelephonyManager.NETWORK_TYPE_LTE:
                return true;
            case TelephonyManager.NETWORK_TYPE_UNKNOWN:
                return false;
            default:
                return false;
        }
    }
}
 public class StringUtils {
    public final static String UTF_8 = "utf-8";
    private static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)";  //正则表达式：验证身份证
    /**
     * 校验身份证
     *
     * @param idCard
     * @return 校验通过返回true，否则返回false
     */
    public static boolean isIDCard(String idCard) {
        return Pattern.matches(REGEX_ID_CARD, idCard);
    }

    /**
     * 判断是否为邮箱
     * @param string
     * @return
     */
    public static boolean isEmail(String string){
        if(TextUtils.isEmpty(string))
            return false;
        Pattern p = Pattern.compile("^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\\.([a-zA-Z0-9_-])+)+$");
        Matcher m = p.matcher(string);
        return m.matches();
    }

    public static boolean isNumber(String string){
        if(TextUtils.isEmpty(string))
            return false;
        Pattern p = Pattern.compile("^(\\d+)$");
        Matcher m = p.matcher(string);
        return m.matches();
    }
    /**
     * 判断该字符串是否为中文
     * @param string
     * @return
     */
    public static boolean isChinese(String string){
        int n = 0;
        for(int i = 0; i < string.length(); i++) {
            n = (int)string.charAt(i);
            if(!(19968 <= n && n <40869)) {
                return false;
            }
        }
        return true;
    }

    //验证邮政编码
    public static boolean checkPost(String post) {
        if (post.matches("[1-9]\\d{5}(?!\\d)")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 判断是否为手机号码
     * @param mobiles
     * @return
     */
    public static boolean isMobileNO(String mobiles) {
        Pattern p = Pattern.compile("^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,6,7,8])|(18[0,5-9]))\\d{8}$");
        Matcher m = p.matcher(mobiles);
        return m.matches();
    }

    /**
     * 判断字符串是否有值，如果为null或者是空字符串或者只有空格或者为"null"字符串，则返回true，否则则返回false
     */
    public static boolean isEmpty(String value) {
        if (value != null && !"".equalsIgnoreCase(value.trim()) && !"null".equalsIgnoreCase(value.trim())) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 判断多个字符串是否相等，如果其中有一个为空字符串或者null，则返回false，只有全相等才返回true
     */
    public static boolean isEquals(String... agrs) {
        String last = null;
        for (int i = 0; i < agrs.length; i++) {
            String str = agrs[i];
            if (isEmpty(str)) {
                return false;
            }
            if (last != null && !str.equalsIgnoreCase(last)) {
                return false;
            }
            last = str;
        }
        return true;
    }
    private final static ThreadLocal<SimpleDateFormat> dateFormater = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    private final static ThreadLocal<SimpleDateFormat> dateFormater2 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

    /**
     * 将字符串转为日期类型
     *
     * @param sdate
     * @return
     */
    public static Date toDate(String sdate) {
        try {
            return dateFormater.get().parse(sdate);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 将日期转换为字符串
     * @param dateToFormat
     * @return
     */
    public static String dateToString(Date dateToFormat){
        String formatString = "yyyy年MM月dd日 HH:mm";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatString);
        return simpleDateFormat.format(dateToFormat);
    }

    /**
     * 判断给定字符串时间是否为今日
     *
     * @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;
    }

    /**
     * 返回String类型的今天的日期
     *
     * @return
     */
    public static String getToday() {
        Calendar cal = Calendar.getInstance();
        String curDate = dateFormater.get().format(cal.getTime());
        curDate = curDate.replace("-", "/");
        return curDate;
    }

    /**
     * @Description： 返回字符串格式的当前时间
     *@return
     */
    public static String getCurrentTime(){
        return dateFormater.get().format(new Date());
    }
    /**
     * 返回一个高亮spannable
     *
     * @param content 文本内容
     * @param color   高亮颜色
     * @param start   起始位置
     * @param end     结束位置
     * @return 高亮spannable
     */
    public static CharSequence getHighLightText(String content, int color, int start, int end) {
        if (TextUtils.isEmpty(content)) {
            return "";
        }
        start = start >= 0 ? start : 0;
        end = end <= content.length() ? end : content.length();
        SpannableString spannable = new SpannableString(content);
        CharacterStyle span = new ForegroundColorSpan(color);
        spannable.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return spannable;
    }

    /**
     * 获取链接样式的字符串，即字符串下面有下划线
     *
     * @param resId 文字资源
     * @return 返回链接样式的字符串
     */
    public static Spanned getHtmlStyleString(Context context, int resId) {
        StringBuilder sb = new StringBuilder();
        sb.append("<a href=\"\"><u><b>").append(UIUtils.getString(context, resId)).append(" </b></u></a>");
        return Html.fromHtml(sb.toString());
    }

    /**
     * 格式化文件大小，不保留末尾的0
     */
    public static String formatFileSize(long len) {
        return formatFileSize(len, false);
    }

    /**
     * 格式化文件大小，保留末尾的0，达到长度一致
     */
    public static String formatFileSize(long len, boolean keepZero) {
        String size;
        DecimalFormat formatKeepTwoZero = new DecimalFormat("#.00");
        DecimalFormat formatKeepOneZero = new DecimalFormat("#.0");
        if (len < 1024) {
            size = String.valueOf(len + "B");
        } else if (len < 10 * 1024) {
            // [0, 10KB)，保留两位小数
            size = String.valueOf(len * 100 / 1024 / (float) 100) + "KB";
        } else if (len < 100 * 1024) {
            // [10KB, 100KB)，保留一位小数
            size = String.valueOf(len * 10 / 1024 / (float) 10) + "KB";
        } else if (len < 1024 * 1024) {
            // [100KB, 1MB)，个位四舍五入
            size = String.valueOf(len / 1024) + "KB";
        } else if (len < 10 * 1024 * 1024) {
            // [1MB, 10MB)，保留两位小数
            if (keepZero) {
                size = String.valueOf(formatKeepTwoZero.format(len * 100 / 1024 / 1024 / (float) 100)) + "MB";
            } else {
                size = String.valueOf(len * 100 / 1024 / 1024 / (float) 100) + "MB";
            }
        } else if (len < 100 * 1024 * 1024) {
            // [10MB, 100MB)，保留一位小数
            if (keepZero) {
                size = String.valueOf(formatKeepOneZero.format(len * 10 / 1024 / 1024 / (float) 10)) + "MB";
            } else {
                size = String.valueOf(len * 10 / 1024 / 1024 / (float) 10) + "MB";
            }
        } else if (len < 1024 * 1024 * 1024) {
            // [100MB, 1GB)，个位四舍五入
            size = String.valueOf(len / 1024 / 1024) + "MB";
        } else {
            // [1GB, ...)，保留两位小数
            size = String.valueOf(len * 100 / 1024 / 1024 / 1024 / (float) 100) + "GB";
        }
        return size;
    }
}
 public class SystemUtils {

    /**
     * 获取android系统版本号
     */
    public static String getOSVersion() {
        String release = android.os.Build.VERSION.RELEASE; // android系统版本号
        release = "android" + release;
        return release;
    }

    /**
     * 获得android系统sdk版本号
     */
    public static String getOSVersionSDK() {
        return android.os.Build.VERSION.SDK;
    }

    /**
     * 获得android系统sdk版本号
     */
    public static int getOSVersionSDKINT() {
        return android.os.Build.VERSION.SDK_INT;
    }

    /**
     * 获取手机型号
     */
    public static String getDeviceModel() {
        return android.os.Build.MODEL;
    }

    /**
     * 获取设备的IMEI
     */
    public static String getIMEI(Context context) {
        if (null == context) {
            return null;
        }
        String imei = null;
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            imei = tm.getDeviceId();
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return imei;
    }

    /**
     * 检测手机是否已插入SIM卡
     */
    public static boolean isCheckSimCardAvailable(Context context) {
        if (null == context) {
            return false;
        }
        final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return tm.getSimState() == TelephonyManager.SIM_STATE_READY;
    }

    /**
     * sim卡是否可读
     */
    public static boolean isCanUseSim(Context context) {
        if (null == context) {
            return false;
        }
        try {
            TelephonyManager mgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            return TelephonyManager.SIM_STATE_READY == mgr.getSimState();
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return false;
    }

    /**
     * 取得当前sim手机卡的imsi
     */
    public static String getIMSI(Context context) {
        if (null == context) {
            return null;
        }
        String imsi = null;
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            imsi = tm.getSubscriberId();
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return imsi;
    }

    /**
     * 返回本地手机号码，这个号码不一定能获取到
     */
    public static String getNativePhoneNumber(Context context) {
        if (null == context) {
            return null;
        }
        TelephonyManager telephonyManager;
        telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        String NativePhoneNumber = null;
        NativePhoneNumber = telephonyManager.getLine1Number();
        return NativePhoneNumber;
    }

    /**
     * 返回手机服务商名字
     */
    public static String getProvidersName(Context context) {
        String ProvidersName = null;

        String IMSI = getIMSI(context);

        if (IMSI.startsWith("46000") || IMSI.startsWith("46002")) {
            ProvidersName = "中国移动";
        } else if (IMSI.startsWith("46001")) {
            ProvidersName = "中国联通";
        } else if (IMSI.startsWith("46003")) {
            ProvidersName = "中国电信";
        } else {
            ProvidersName = "其他服务商:" + IMSI;
        }
        return ProvidersName;
    }

    /**
     * 判断当前网络状态
     *
     * @param mcontext
     * @return
     */
    public static String getCurrentNetState(Context mcontext) {
        ConnectivityManager connectivityManager = (ConnectivityManager) mcontext
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            TelephonyManager mTelephony = (TelephonyManager) mcontext
                    .getSystemService(Context.TELEPHONY_SERVICE);
            int netType = info.getType();
            int netSubtype = info.getSubtype();
            if (netType == ConnectivityManager.TYPE_WIFI) {// WIFI
                return "WIFI";
            } else if (netType == ConnectivityManager.TYPE_MOBILE
                    && netSubtype == TelephonyManager.NETWORK_TYPE_UMTS
                    && !mTelephony.isNetworkRoaming()) {// 3G
                return "3G";
            } else {
                return "2G";
            }
        }
        return null;
    }

    /**
     * 获取当前设备的SN
     */
    public static String getSimSN(Context context) {
        if (null == context) {
            return null;
        }
        String simSN = null;
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            simSN = tm.getSimSerialNumber();
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return simSN;
    }

    /**
     * 获取当前设备的MAC地址
     */
    public static String getMacAddress(Context context) {
        if (null == context) {
            return null;
        }
        String mac = null;
        try {
            WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            WifiInfo info = wm.getConnectionInfo();
            mac = info.getMacAddress();
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return mac;
    }

    /**
     * 获得设备ip地址
     */
    public static String getLocalAddress() {
        try {
            Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
            while (en.hasMoreElements()) {
                NetworkInterface intf = en.nextElement();
                Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses();
                while (enumIpAddr.hasMoreElements()) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        return inetAddress.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            LogUtils.e(e);
        }
        return null;
    }

    /**
     * 获取屏幕的分辨率
     */
    @SuppressWarnings("deprecation")
    public static int[] getResolution(Context context) {
        if (null == context) {
            return null;
        }
        WindowManager windowMgr = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        int[] res = new int[2];
        res[0] = windowMgr.getDefaultDisplay().getWidth();
        res[1] = windowMgr.getDefaultDisplay().getHeight();
        return res;
    }

    /**
     * 获得设备的横向dpi
     */
    public static float getWidthDpi(Context context) {
        if (null == context) {
            return 0;
        }
        DisplayMetrics dm = null;
        try {
            if (context != null) {
                dm = new DisplayMetrics();
                dm = context.getApplicationContext().getResources().getDisplayMetrics();
            }
            return dm.densityDpi;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获得设备的纵向dpi
     */
    public static float getHeightDpi(Context context) {
        if (null == context) {
            return 0;
        }
        DisplayMetrics dm = new DisplayMetrics();
        dm = context.getApplicationContext().getResources().getDisplayMetrics();
        return dm.ydpi;
    }

    /**
     * 获得设备的横向px
     */
    public static float getWidthPx(Context context) {
        if (null == context) {
            return 0;
        }
        DisplayMetrics dm = null;
        try {
            if (context != null) {
                dm = new DisplayMetrics();
                dm = context.getApplicationContext().getResources().getDisplayMetrics();
            }
            return dm.widthPixels;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获得设备的纵向px
     */
    public static float getHeightPx(Context context) {
        if (null == context) {
            return 0;
        }
        DisplayMetrics dm = new DisplayMetrics();
        dm = context.getApplicationContext().getResources().getDisplayMetrics();
        return dm.heightPixels;
    }

    /**
     * 获取设备信息
     */
    public static String[] getDivceInfo() {
        String str1 = "/proc/cpuinfo";
        String str2 = "";
        String[] cpuInfo = {"", ""};
        String[] arrayOfString;
        try {
            FileReader fr = new FileReader(str1);
            BufferedReader localBufferedReader = new BufferedReader(fr, 8192);
            str2 = localBufferedReader.readLine();
            arrayOfString = str2.split("\\s+");
            for (int i = 2; i < arrayOfString.length; i++) {
                cpuInfo[0] = cpuInfo[0] + arrayOfString[i] + " ";
            }
            str2 = localBufferedReader.readLine();
            arrayOfString = str2.split("\\s+");
            cpuInfo[1] += arrayOfString[2];
            localBufferedReader.close();
        } catch (IOException e) {
            LogUtils.e(e);
        }
        return cpuInfo;
    }

    /**
     * 判断手机CPU是否支持NEON指令集
     */
    public static boolean isNEON() {
        boolean isNEON = false;
        String cupinfo = getCPUInfos();
        if (cupinfo != null) {
            cupinfo = cupinfo.toLowerCase();
            isNEON = cupinfo != null && cupinfo.contains("neon");
        }
        return isNEON;
    }

    /**
     * 读取CPU信息文件，获取CPU信息
     */
    @SuppressWarnings("resource")
    private static String getCPUInfos() {
        String str1 = "/proc/cpuinfo";
        String str2 = "";
        StringBuilder resusl = new StringBuilder();
        String resualStr = null;
        try {
            FileReader fr = new FileReader(str1);
            BufferedReader localBufferedReader = new BufferedReader(fr, 8192);
            while ((str2 = localBufferedReader.readLine()) != null) {
                resusl.append(str2);
                // String cup = str2;
            }
            if (resusl != null) {
                resualStr = resusl.toString();
                return resualStr;
            }
        } catch (IOException e) {
            LogUtils.e(e);
        }
        return resualStr;
    }

    /**
     * 获取当前设备cpu的型号
     */
    public static int getCPUModel() {
        return matchABI(getSystemProperty("ro.product.cpu.abi")) | matchABI(getSystemProperty("ro.product.cpu.abi2"));
    }

    /**
     * 匹配当前设备的cpu型号
     */
    private static int matchABI(String abiString) {
        if (TextUtils.isEmpty(abiString)) {
            return 0;
        }
        if ("armeabi".equals(abiString)) {
            return 1;
        } else if ("armeabi-v7a".equals(abiString)) {
            return 2;
        } else if ("x86".equals(abiString)) {
            return 4;
        } else if ("mips".equals(abiString)) {
            return 8;
        }
        return 0;
    }

    /**
     * 获取CPU核心数
     */
    public static int getCpuCount() {
        return Runtime.getRuntime().availableProcessors();
    }

    /**
     * 获取Rom版本
     */
    public static String getRomversion() {
        String rom = "";
        try {
            String modversion = getSystemProperty("ro.modversion");
            String displayId = getSystemProperty("ro.build.display.id");
            if (modversion != null && !modversion.equals("")) {
                rom = modversion;
            }
            if (displayId != null && !displayId.equals("")) {
                rom = displayId;
            }
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return rom;
    }

    /**
     * 获取系统配置参数
     */
    public static String getSystemProperty(String key) {
        String pValue = null;
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method m = c.getMethod("get", String.class);
            pValue = m.invoke(null, key).toString();
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return pValue;
    }

    /**
     * 获取系统中的Library包
     */
    public static List<String> getSystemLibs(Context context) {
        if (null == context) {
            return null;
        }
        PackageManager pm = context.getPackageManager();
        String[] libNames = pm.getSystemSharedLibraryNames();
        List<String> listLibNames = Arrays.asList(libNames);
        LogUtils.d("SystemLibs: " + listLibNames);
        return listLibNames;
    }

    /**
     * 获取手机外部可用空间大小，单位为byte
     */
    @SuppressWarnings("deprecation")
    public static long getExternalTotalSpace() {
        long totalSpace = -1L;
        if (FileUtils.isSDCardAvailable()) {
            try {
                String path = Environment.getExternalStorageDirectory().getPath();// 获取外部存储目录即 SDCard
                StatFs stat = new StatFs(path);
                long blockSize = stat.getBlockSize();
                long totalBlocks = stat.getBlockCount();
                totalSpace = totalBlocks * blockSize;
            } catch (Exception e) {
                LogUtils.e(e);
            }
        }
        return totalSpace;
    }

    /**
     * 获取外部存储可用空间，单位为byte
     */
    @SuppressWarnings("deprecation")
    public static long getExternalSpace() {
        long availableSpace = -1L;
        if (FileUtils.isSDCardAvailable()) {
            try {
                String path = Environment.getExternalStorageDirectory().getPath();
                StatFs stat = new StatFs(path);
                availableSpace = stat.getAvailableBlocks() * (long) stat.getBlockSize();
            } catch (Exception e) {
                LogUtils.e(e);
            }
        }
        return availableSpace;
    }

    /**
     * 获取手机内部空间大小，单位为byte
     */
    @SuppressWarnings("deprecation")
    public static long getTotalInternalSpace() {
        long totalSpace = -1L;
        try {
            String path = Environment.getDataDirectory().getPath();
            StatFs stat = new StatFs(path);
            long blockSize = stat.getBlockSize();
            long totalBlocks = stat.getBlockCount();// 获取该区域可用的文件系统数
            totalSpace = totalBlocks * blockSize;
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return totalSpace;
    }

    /**
     * 获取手机内部可用空间大小，单位为byte
     */
    @SuppressWarnings("deprecation")
    public static long getAvailableInternalMemorySize() {
        long availableSpace = -1l;
        try {
            String path = Environment.getDataDirectory().getPath();// 获取 Android 数据目录
            StatFs stat = new StatFs(path);// 一个模拟linux的df命令的一个类,获得SD卡和手机内存的使用情况
            long blockSize = stat.getBlockSize();// 返回 Int ，大小，以字节为单位，一个文件系统
            long availableBlocks = stat.getAvailableBlocks();// 返回 Int ，获取当前可用的存储空间
            availableSpace = availableBlocks * blockSize;
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return availableSpace;
    }

    /**
     * 获取单个应用最大分配内存，单位为byte
     */
    public static long getOneAppMaxMemory(Context context) {
        if (context == null) {
            return -1;
        }
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        return activityManager.getMemoryClass() * 1024 * 1024;
    }

    /**
     * 获取指定本应用占用的内存，单位为byte
     */
    public static long getUsedMemory(Context context) {
        return getUsedMemory(context, null);
    }

    /**
     * 获取指定包名应用占用的内存，单位为byte
     */
    public static long getUsedMemory(Context context, String packageName) {
        if (context == null) {
            return -1;
        }
        if (StringUtils.isEmpty(packageName)) {
            packageName = context.getPackageName();
        }
        long size = 0;
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> runapps = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo runapp : runapps) { // 遍历运行中的程序
            if (packageName.equals(runapp.processName)) {// 得到程序进程名，进程名一般就是包名，但有些程序的进程名并不对应一个包名
                // 返回指定PID程序的内存信息，可以传递多个PID，返回的也是数组型的信息
                Debug.MemoryInfo[] processMemoryInfo = activityManager.getProcessMemoryInfo(new int[]{runapp.pid});
                // 得到内存信息中已使用的内存，单位是K
                size = processMemoryInfo[0].getTotalPrivateDirty() * 1024;
            }
        }
        return size;
    }

    /**
     * 获取手机剩余内存，单位为byte
     */
    public static long getAvailableMemory(Context context) {
        if (context == null) {
            return -1;
        }
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
        activityManager.getMemoryInfo(info);
        return info.availMem;
    }

    /**
     * 获取手机总内存，单位为byte
     */
    public static long getTotalMemory() {
        long size = 0;
        String path = "/proc/meminfo";// 系统内存信息文件
        try {
            String totalMemory = FileUtils.readProperties(path, "MemTotal", null);// 读出来是带单位kb的，并且单位前有空格，所以去掉最后三位
            if (!StringUtils.isEmpty(totalMemory) && totalMemory.length() > 3) {
                size = Long.valueOf(totalMemory.substring(0, totalMemory.length() - 3)) * 1024;
            }
        } catch (Exception e) {
            LogUtils.e(e);
        }
        return size;
    }

    /**
     * 手机低内存运行阀值，单位为byte
     */
    public static long getThresholdMemory(Context context) {
        if (context == null) {
            return -1;
        }
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
        activityManager.getMemoryInfo(info);
        return info.threshold;
    }

    /**
     * 手机是否处于低内存运行
     */
    public static boolean isLowMemory(Context context) {
        if (context == null) {
            return false;
        }
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
        activityManager.getMemoryInfo(info);
        return info.lowMemory;
    }


}
 public class UIUtils {
    public static BaseApplication getApplication() {
        return BaseApplication.getApplication();
    }

    public static Thread getMainThread() {
        return BaseApplication.getMainThread();
    }

    public static long getMainThreadId() {
        return BaseApplication.getMainThreadId();
    }

    public static Toast toast;

    public static final boolean isEmail(String value) {
        return android.util.Patterns.EMAIL_ADDRESS.matcher(value).matches();
    }

    public static String getVersion(Context context)// 获取版本号
    {
        PackageInfo pi = null;
        try {
            pi = context.getPackageManager().getPackageInfo(
                    context.getPackageName(), 0);

        } catch (PackageManager.NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return pi.versionName;
    }

    public static void setImageUrl(Context context, String imageUrl, ImageView view) {
        Picasso.with(context).load(imageUrl)
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher)
                .into(view);
    }

    public static void setImageUrl(Context context, String imageUrl, Target target) {
        Picasso.with(context).load(imageUrl)
                .placeholder(R.mipmap.ic_launcher)
                .error(R.mipmap.ic_launcher)
                .into(target);
    }

    /**
     * dip转换px
     */
    public static int dip2px(Context context, int dip) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dip * scale + 0.5f);
    }

    /**
     * pxz转换dip
     */
    public static int px2dip(Context context, int px) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (px / scale + 0.5f);
    }


    /**
     * 获取主线程的handler
     */
    public static Handler getHandler() {
        return BaseApplication.getMainThreadHandler();
    }

    /**
     * 延时在主线程执行runnable
     */
    public static boolean postDelayed(Runnable runnable, long delayMillis) {
        return getHandler().postDelayed(runnable, delayMillis);
    }

    /**
     * 在主线程执行runnable
     */
    public static boolean post(Runnable runnable) {
        return getHandler().post(runnable);
    }

    /**
     * 从主线程looper里面移除runnable
     */
    public static void removeCallbacks(Runnable runnable) {
        getHandler().removeCallbacks(runnable);
    }

    public static View inflate(Context context, int resId) {
        return LayoutInflater.from(context).inflate(resId, null);
    }

    /**
     * 获取资源
     */
    public static Resources getResources(Context context) {
        return context.getResources();
    }

    /**
     * 获取文字
     */
    public static String getString(Context context, int resId) {
        return getResources(context).getString(resId);
    }

    /**
     * 获取文字数组
     */
    public static String[] getStringArray(Context context, int resId) {
        return getResources(context).getStringArray(resId);
    }

    /**
     * 获取dimen
     */
    public static int getDimens(Context context, int resId) {
        return getResources(context).getDimensionPixelSize(resId);
    }

    /**
     * 获取drawable
     */
    public static Drawable getDrawable(Context context, int resId) {
        return getResources(context).getDrawable(resId);
    }

    /**
     * 获取颜色
     */
    public static int getColor(Context context, int resId) {
        return getResources(context).getColor(resId);
    }

    /**
     * 获取颜色选择器
     */
    public static ColorStateList getColorStateList(Context context, int resId) {
        return getResources(context).getColorStateList(resId);
    }

    //判断当前的线程是不是在主线程
    public static boolean isRunInMainThread() {
        return android.os.Process.myTid() == getMainThreadId();
    }

    public static void runInMainThread(Runnable runnable) {
        if (isRunInMainThread()) {
            runnable.run();
        } else {
            post(runnable);
        }
    }


    /**
     * 对toast的简易封装。线程安全，可以在非UI线程调用。
     */
    public static void showToastSafe(Context context, final int resId) {
        showToastSafe(context, getString(context, resId));
    }

    /**
     * 对toast的简易封装。线程安全，可以在非UI线程调用。
     */
    public static void showToastSafe(final Context context, final String str) {
        if (isRunInMainThread()) {
            showToast(context, str);
        } else {
            post(new Runnable() {
                @Override
                public void run() {
                    showToast(context, str);
                }
            });
        }
    }

    /**
     * 添加 弱引用，避免内存泄漏
     * @param context
     * @param str
     */
    private static void showToast(Context context, String str) {
        WeakReference<Context> contextWeakReference = new WeakReference<>(context);
        if (toast == null) {
            toast = Toast.makeText(contextWeakReference.get().getApplicationContext(), str, Toast.LENGTH_SHORT);
        } else {
            toast.setText(str);
            toast.setDuration(Toast.LENGTH_SHORT);
        }
        toast.show();
    }


//    /**
//     * 高斯模糊
//     *
//     * @param ctx
//     * @param view
//     * @param textView
//     */
//    public static void ninePatchDrawable(final Context ctx, final ImageView view, final TextView textView) {
//        Drawable drawable = view.getDrawable();
//        if (drawable instanceof BitmapDrawable) {
//            synchronized (UIUtils.class) {
//
//                view.setImageBitmap(Blur.apply(ctx, ((BitmapDrawable) view.getDrawable()).getBitmap()));
//            }
//
//
//        } else if (drawable instanceof NinePatchDrawable) {
//            Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
//            Canvas canvas = new Canvas(bitmap);
//            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
//            drawable.draw(canvas);
//            view.setImageBitmap(Blur.apply(ctx, bitmap));
//        }
//        view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
//
//            @Override
//            public boolean onPreDraw() {
//                view.getViewTreeObserver().removeOnPreDrawListener(this);
//                view.buildDrawingCache();
//                Bitmap bmp = view.getDrawingCache();
//                ViewUtils.blur(ctx, bmp, textView);
//                return true;
//            }
//        });
//
//    }


    }
 public class ViewUtils {
    /**
     * 把自身从父View中移除
     */
    public static void removeSelfFromParent(View view) {
        if (view != null) {
            ViewParent parent = view.getParent();
            if (parent != null && parent instanceof ViewGroup) {
                ViewGroup group = (ViewGroup) parent;
                group.removeView(view);
            }
        }
    }

    /**
     * 请求View树重新布局，用于解决中层View有布局状态而导致上层View状态断裂
     */
    public static void requestLayoutParent(View view, boolean isAll) {
        ViewParent parent = view.getParent();
        while (parent != null && parent instanceof View) {
            if (!parent.isLayoutRequested()) {
                parent.requestLayout();
                if (!isAll) {
                    break;
                }
            }
            parent = parent.getParent();
        }
    }

    /**
     * 根据图片的url路径获得Bitmap对象
     *
     * @param url
     * @return
     */
    public static Bitmap returnBitmap(String url) {
        URL fileUrl = null;
        Bitmap bitmap = null;

        try {
            fileUrl = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        try {
            HttpURLConnection conn = (HttpURLConnection) fileUrl
                    .openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;

    }

    /**
     * 判断触点是否落在该View上
     */
    public static boolean isTouchInView(MotionEvent ev, View v) {
        int[] vLoc = new int[2];
        v.getLocationOnScreen(vLoc);
        float motionX = ev.getRawX();
        float motionY = ev.getRawY();
        return motionX >= vLoc[0] && motionX <= (vLoc[0] + v.getWidth()) && motionY >= vLoc[1] && motionY <= (vLoc[1] + v.getHeight());
    }

    /**
     * FindViewById的泛型封装，减少强转代码
     */
    public static <T extends View> T findViewById(View layout, int id) {
        return (T) layout.findViewById(id);
    }

    public static Bitmap bigImage(Bitmap bmp, float big) {
        int bmpWidth = bmp.getWidth();
        int bmpHeight = bmp.getHeight();
        /* 产生reSize后的Bitmap对象 */
        Matrix matrix = new Matrix();
        matrix.postScale(big, big);
        Bitmap resizeBmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth,
                bmpHeight, matrix, true);

        return resizeBmp;
    }

    /**
     * sp2Px
     *
     * @param context context
     * @param sp      sp
     * @return float
     */
    public static float sp2Px(Context context, int sp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                context.getResources().getDisplayMetrics());
    }

    /**
     * sp2Px
     *
     * @param sp sp
     * @return float
     */
    public static float sp2Px(int sp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                BaseApplication.getInstance().getResources().getDisplayMetrics());
    }

    /**
     * dp2Px
     *
     * @param context context
     * @param dp      dp
     * @return float
     */
    public static float dp2Px(Context context, int dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                context.getResources().getDisplayMetrics());
    }

    /**
     * dp2Px
     *
     * @param dp dp
     * @return float
     */
    public static float dp2Px(int dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                BaseApplication.getInstance().getResources().getDisplayMetrics());
    }

    /**
     * px2Dp
     *
     * @param context context
     * @param px      px
     * @return float
     */
    public static float px2Dp(Context context, int px) {
        return context.getResources().getDisplayMetrics().density * px;
    }

    /**
     * px2Dp
     *
     * @param px px
     * @return float
     */
    public static float px2Dp(int px) {
        return BaseApplication.getInstance().getResources().getDisplayMetrics().density * px;
    }

//    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
//    public static void blur(Context context, Bitmap bkg, View view) {
//        int radius = 20;
//        Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth()), (int) (view.getMeasuredHeight()), Bitmap.Config.ARGB_8888);
//        Canvas canvas = new Canvas(overlay);
//        canvas.translate(-view.getLeft(), -view.getTop());
//        canvas.drawBitmap(bkg, 0, 0, null);
//        view.setBackground(new BitmapDrawable(context.getResources(), Blur.apply(context, overlay, radius)));
//    }

    public static void tvUnderLine(TextView textView) {
        textView.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG); //下划线
        textView.getPaint().setAntiAlias(true);//抗锯齿
    }


    static PopupWindow popupWindow;

    /**
     * 弹出popupwindow
     * @param context
     * @param resId 布局layoutID
     * @param root  显示到哪个View下
     * @param paramsType    布局参数类型：1-都是match；2- ； 3-
     * @return  布局解析得到的View，便于后续findViewById
     */
    public static View showPopupWindow(Context context, int resId, View root,int paramsType) {
        // 一个自定义的布局，作为显示的内容
        View popupView;
        popupView = LayoutInflater.from(context).inflate(resId, null);

        switch (paramsType){
            case 1 :    //宽高全都是match_parent
                popupWindow = new PopupWindow(popupView,
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);
                break;
            case 2 :    //宽是match，高是wrap
                popupWindow = new PopupWindow(popupView,
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
                break;
            case 3  :   //宽是wrap，高是match
                popupWindow = new PopupWindow(popupView,
                        ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, true);
                break;
            case 4  :   //宽、高都是wrap
                popupWindow = new PopupWindow(popupView,
                        ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
                break;
            default:
                popupWindow = new PopupWindow(popupView,
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);
                break;
        }
        popupWindow.setFocusable(true);
        popupWindow.setOutsideTouchable(true);
        popupWindow.setTouchable(true);
        popupWindow.setBackgroundDrawable(new BitmapDrawable());
        popupWindow.showAsDropDown(root);
//        popupWindow.show

        return popupView;
    }

    /**
     * 关闭popup
     */
    public static void dismissPopup(){
        if (popupWindow != null && popupWindow.isShowing()){
            popupWindow.dismiss();
            popupWindow = null;
        }
    }
}
 public class ExtendMediaPicker implements View.OnClickListener {
    private static final String TAG = "ExtendMediaPicker";
    public static final int REQUEST_CODE_CROP_PHOTO = 2000;
    public static final int REQUEST_CODE_PICK_IMAGE = 2001;
    public static final int REQUEST_CODE_TAKE_PHOTO = 2002;

    private Uri imageUri;
    private File tempFile;
    private boolean mCropImage;
    private Fragment mFragment;
    private Activity mActivity;
    private OnMediaPickerListener mMediaPickerListener;
    private ImageView imgViewTarget;
    private boolean isActivity;
    private View popView;
    private PopupWindow pop;

    public ExtendMediaPicker(Fragment fragment) {
        this.mFragment = fragment;
        this.tempFile = createTempFile();
        this.isActivity = false;
    }

    public ExtendMediaPicker(Activity fragment) {
        this.mActivity = fragment;
        this.tempFile = createTempFile();
        this.isActivity = true;
    }

    public ExtendMediaPicker(Activity fragment, ImageView targetImgView) {
        this.mActivity = fragment;
        this.tempFile = createTempFile();
        this.isActivity = true;
        this.imgViewTarget = targetImgView;
    }

    public void showPickerView(boolean isCropImage, View mIvUserImage) {
        this.mCropImage = isCropImage;
        popView = View.inflate(UIUtils.getApplication(),
                R.layout.pop_chose_photo, null);
        popView.findViewById(R.id.tv_camer).setOnClickListener(this);
        popView.findViewById(R.id.tv_gallery).setOnClickListener(this);
        popView.findViewById(R.id.tv_cancle).setOnClickListener(this);


        pop = new PopupWindow(popView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT,
                true);


        pop.setOutsideTouchable(true);

        pop.setFocusable(true);


        pop.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        pop.setAnimationStyle(R.style.AnimBottom);

//        pop.showAsDropDown(mIvUserImage);
        pop.showAtLocation(mIvUserImage, Gravity.BOTTOM, 0, 0);
    }


    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) {

            return;
        }

        LogUtils.e(TAG,"onActivityResult");
        switch (requestCode) {
            case REQUEST_CODE_PICK_IMAGE:
                String path = MediaUtils.getPath(isActivity == false ? mFragment.getContext() : mActivity, data.getData());
                cropImageUri(Uri.fromFile(new File(path)), 300, 300,
                        REQUEST_CODE_CROP_PHOTO);
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                this.imgViewTarget.setImageBitmap(bitmap);
                break;
            case REQUEST_CODE_TAKE_PHOTO:

                cropImageUri(imageUri, 300, 300, REQUEST_CODE_CROP_PHOTO);
                break;
            case REQUEST_CODE_CROP_PHOTO:
                String imagePath = tempFile.getAbsolutePath();
                LogUtils.i("crop" + imagePath);

                if (mMediaPickerListener != null) {


                    mMediaPickerListener.onSelectedMediaChanged(imagePath);
                }
                break;
        }


    }

    @SuppressLint("InlinedApi")
    private void openSystemPickImage() {
        Intent photoPickerIntent = null;
        if (Build.VERSION.SDK_INT < 19) {
            photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
        } else {
            photoPickerIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        }
        photoPickerIntent.setType("image/*");
        photoPickerIntent.addCategory(Intent.CATEGORY_OPENABLE);
        if (!isActivity) {
            mFragment.startActivityForResult(photoPickerIntent,
                    REQUEST_CODE_PICK_IMAGE);
        } else {
            mActivity.startActivityForResult(photoPickerIntent,
                    REQUEST_CODE_PICK_IMAGE);
        }
    }

    private void openSystemCamera() {
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            File dirPath = new File(Environment.getExternalStorageDirectory(),
                    System.currentTimeMillis() + ".jpg");
            imageUri = Uri.fromFile(dirPath);

            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);


            if (!isActivity) {
                mFragment.startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
            } else {
                mActivity.startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
            }

        } else {
            UIUtils.showToastSafe(UIUtils.getApplication(),
                    "Before you take photos please insert SD card");
        }
    }

    private File createTempFile() {
        File file = null;
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            return new File(Environment.getExternalStorageDirectory(),
                    +System.currentTimeMillis() + "image.png");
        } else {


            if (!isActivity) {
                file = new File(mFragment.getContext().getFilesDir(), +System.currentTimeMillis() + "image.png");
            } else {
                file = new File(mActivity.getFilesDir(), +System.currentTimeMillis() + "image.png");

            }

            return file;
        }
    }

    /**
     * 截取图像部分区域
     *
     * @param uri
     * @param outputX
     * @param outputY
     * @return
     */
    private void cropImageUri(Uri uri, int outputX, int outputY, int requestCode) {
        if (!mCropImage && mMediaPickerListener != null) {
            mMediaPickerListener.onSelectedMediaChanged(uri.getPath());
            return;
        }

        try {
            // android1.6以后只能传图库中图片
            Intent intent = new Intent("com.android.camera.action.CROP");
            intent.setDataAndType(uri, "image/*");
            intent.putExtra("crop", "true");
            intent.putExtra("aspectX", 1);
            intent.putExtra("aspectY", 1);
            intent.putExtra("outputX", outputX);
            intent.putExtra("outputY", outputY);
            intent.putExtra("scale", true);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
            intent.putExtra("return-data", false);
            intent.putExtra("outputFormat",
                    Bitmap.CompressFormat.JPEG.toString());
            intent.putExtra("noFaceDetection", true);


            if (!isActivity) {
                mFragment.startActivityForResult(intent, requestCode);

            } else {
                mActivity.startActivityForResult(intent, requestCode);

            }


        } catch (ActivityNotFoundException ex) {
            UIUtils.showToastSafe(UIUtils.getApplication(), "Can not find image crop app");
        }
    }

    public void setOnMediaPickerListener(OnMediaPickerListener listener) {
        this.mMediaPickerListener = listener;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_camer:
                if (PerssionUtils.checkPerssion(mActivity, Manifest.permission.CAMERA) && PerssionUtils.checkPerssion(mActivity, Manifest.permission.READ_EXTERNAL_STORAGE)) {

                    openSystemCamera();
                    disMissPop();
                }
                break;
            case R.id.tv_gallery:
                if (PerssionUtils.checkPerssion(mActivity, Manifest.permission.CAMERA) && PerssionUtils.checkPerssion(mActivity, Manifest.permission.READ_EXTERNAL_STORAGE)) {
                    openSystemPickImage();
                    disMissPop();
                }
                break;
            case R.id.tv_cancle:
                disMissPop();
                break;
        }
    }

    public interface OnMediaPickerListener {

        void onSelectedMediaChanged(String mediaUri);
    }


    private void disMissPop() {
        if (pop != null && pop.isShowing()) {
            pop.dismiss();
        }
    }
}

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.media.ThumbnailUtils;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.avos.avoscloud.AVException;
import com.avos.avoscloud.AVObject;
import com.avos.avoscloud.RefreshCallback;
import com.avos.avoscloud.SaveCallback;
import com.squareup.picasso.MemoryPolicy;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import net.sxkeji.markdownlib.MarkdownView;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import butterknife.Bind;
import butterknife.ButterKnife;
import sxkeji.net.dailydiary.Article;
import net.sxkeji.dailydiary.R;
import sxkeji.net.dailydiary.common.BaseApplication;
import sxkeji.net.dailydiary.http.HttpClient;
import sxkeji.net.dailydiary.storage.Constant;
import sxkeji.net.dailydiary.storage.SharedPreferencesUtils;
import sxkeji.net.dailydiary.utils.FileUtils;
import sxkeji.net.dailydiary.utils.LogUtils;
import sxkeji.net.dailydiary.utils.MediaUtils;
import sxkeji.net.dailydiary.utils.NetWorkUtils;
import sxkeji.net.dailydiary.utils.StringUtils;
import sxkeji.net.dailydiary.utils.SystemUtils;
import sxkeji.net.dailydiary.utils.UIUtils;
import sxkeji.net.dailydiary.utils.ViewUtils;
import sxkeji.net.dailydiary.widgets.ExtendMediaPicker;
package sxkeji.net.dailydiary.common.activities;






/**
 * 写文字页面
 * Created by zhangshixin on 3/17/2016.
 */
public class ArticleWriteActivity extends AppCompatActivity {
    private static final String TAG = "ArticleWriteActivity";

    @Bind(R.id.toolbar)
    Toolbar toolbar;
    @Bind(R.id.tv_no_img_header)
    TextView tvNoImgHeader;
    @Bind(R.id.layout_select_img)
    RelativeLayout layoutSelectImg;
    //    @Bind(R.id.et_content)
//    EditText etContent;
    @Bind(R.id.img_select)
    ImageView imgSelect;

    @Bind(R.id.collapsing_toolbar_layout)
    CollapsingToolbarLayout collapsingToolbarLayout;
    //    @Bind(R.id.ll_write_normal)
//    LinearLayout llWriteNormal;
//    @Bind(R.id.view_markdown)
//    net.sxkeji.markdownlib.MarkdownView viewMarkdown;
    @Bind(R.id.et_markdown)
    EditText etMarkdown;
    @Bind(R.id.ll_write_markdown)
    LinearLayout llWriteMarkdown;
    @Bind(R.id.fab_preview_save)
    FloatingActionButton fabPreviewSave;
    private ExtendMediaPicker mediaPicker;