├── images
└── 0.jpg
├── ic_launcher-web.png
├── libs
├── android-support-v4.jar
└── universal-image-loader-1.8.6.jar
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ ├── ic_launcher.png
│ ├── round_conner_bg.9.png
│ └── default_round_avatar2.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── values-sw600dp
│ └── dimens.xml
├── values
│ ├── dimens.xml
│ ├── strings.xml
│ ├── attrs_weblimitimageview.xml
│ └── styles.xml
├── menu
│ └── main.xml
├── values-sw720dp-land
│ └── dimens.xml
├── values-v11
│ └── styles.xml
├── values-v14
│ └── styles.xml
└── layout
│ └── activity_main.xml
├── .settings
└── org.eclipse.jdt.core.prefs
├── README.md
├── src
└── com
│ └── example
│ ├── cache
│ ├── IImageCache.java
│ ├── CacheHelper.java
│ ├── ImageLoaderHandler.java
│ ├── MemImageCache.java
│ ├── LocalCache.java
│ ├── DiskImageCache.java
│ └── ImageLoader.java
│ ├── widget
│ ├── ArcFourConnerAvatarImageView.java
│ ├── WebImageView.java
│ ├── WebLimitImageView.java
│ └── ArcAvatarImageView.java
│ ├── android_arcavatarimageview
│ └── MainActivity.java
│ ├── MyApp.java
│ ├── support
│ ├── ConfigWrapper.java
│ ├── ConnectivitySupport.java
│ ├── MediaFile.java
│ └── SystemSupport.java
│ └── utils
│ ├── ImageLoaderUtils.java
│ ├── CommUtils.java
│ ├── BitmapUtils.java
│ ├── BitmapWorkerTask.java
│ └── Utils.java
├── .classpath
├── project.properties
├── proguard-project.txt
├── .project
└── AndroidManifest.xml
/images/0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/images/0.jpg
--------------------------------------------------------------------------------
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/ic_launcher-web.png
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/libs/universal-image-loader-1.8.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/libs/universal-image-loader-1.8.6.jar
--------------------------------------------------------------------------------
/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/round_conner_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/res/drawable-xhdpi/round_conner_bg.9.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/default_round_avatar2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/ArcImageView/HEAD/res/drawable-xhdpi/default_round_avatar2.png
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ArcImageView
2 | Custom ImageView is designed to support loading network and local image, which has rounded corners, or is rounded (支持加载网络、本地的图片的四角圆角或圆形的ImageView)
3 | 效果图:
4 | 
5 |
--------------------------------------------------------------------------------
/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/com/example/cache/IImageCache.java:
--------------------------------------------------------------------------------
1 | package com.example.cache;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | /**
6 | * 图片缓存的接口
7 | * @author Jack
8 | */
9 | public interface IImageCache {
10 |
11 | public Bitmap getBitmap(String url);
12 |
13 | public boolean putBitmap(String url, Bitmap bitmap);
14 |
15 | public boolean putBitmap(String url, byte[] imageData);
16 |
17 | public void clearImage();
18 |
19 | public boolean hasImage(String url);
20 |
21 | public boolean removeImage(String url);
22 | }
23 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Android_ArcAvatarImageView
5 | Settings
6 | Hello world!
7 |
8 | 刚刚
9 | 分钟前
10 | 小时前
11 | 天前
12 | 您没有安装SD卡哦!
13 | SD卡存储空间不足!
14 |
15 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 |
--------------------------------------------------------------------------------
/src/com/example/widget/ArcFourConnerAvatarImageView.java:
--------------------------------------------------------------------------------
1 | package com.example.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.util.AttributeSet;
6 |
7 |
8 |
9 | /**
10 | * 四角圆角背景图ImageView
11 | * @author Jack
12 | * @version 创建时间:2013-9-5 下午2:55:12
13 | */
14 | public class ArcFourConnerAvatarImageView extends ArcAvatarImageView {
15 |
16 | public ArcFourConnerAvatarImageView(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | /**
21 | * 圆角头像图片显示
22 | */
23 | public void setImageBitmap(Bitmap bm) {
24 | setImageBitmapRoundConer(bm);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/com/example/widget/WebImageView.java:
--------------------------------------------------------------------------------
1 | package com.example.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.ImageView;
6 |
7 |
8 | /**
9 | * 可以加载指定url图片的ImageView
10 | */
11 | public class WebImageView extends ImageView {
12 |
13 | protected String mCurrentUrl;
14 |
15 | public WebImageView(Context context) {
16 | this(context, null);
17 | }
18 |
19 | public WebImageView(Context context, AttributeSet attributes) {
20 | super(context, attributes);
21 | }
22 |
23 | /**
24 | * @return the mImageUrl
25 | */
26 | public String getImageUrl() {
27 | return mCurrentUrl;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/com/example/cache/CacheHelper.java:
--------------------------------------------------------------------------------
1 |
2 | package com.example.cache;
3 |
4 | /**
5 | * 缓存的辅助类:
6 | * 1、获得url图片的后缀
7 | * 2、由url字符串生成本地文件名。
8 | * @author Jack
9 | */
10 |
11 | public class CacheHelper {
12 | public static String getSuffix(String remote) {
13 | int start = remote.lastIndexOf(".");
14 | int end = remote.lastIndexOf("?version=");
15 | end = (-1 == end || end <= start) ? remote.length() : end;
16 | String suffix = remote.substring(start, end);
17 |
18 | return suffix;
19 | }
20 |
21 | public static String getFileNameFromUrl(String url) {
22 | // replace all special URI characters with a single + symbol
23 | return url.replaceAll("[:/,%?&=]", "+").replaceAll("[+]+", "+") + getSuffix(url);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Android_ArcAvatarImageView
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
14 |
15 |
16 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/res/values/attrs_weblimitimageview.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/com/example/android_arcavatarimageview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.android_arcavatarimageview;
2 |
3 | import com.example.utils.ImageLoaderUtils;
4 | import com.example.widget.ArcAvatarImageView;
5 | import com.example.widget.ArcFourConnerAvatarImageView;
6 | import com.nostra13.universalimageloader.core.ImageLoader;
7 | import android.os.Bundle;
8 | import android.app.Activity;
9 |
10 | /**
11 | * @author Jack
12 | */
13 | public class MainActivity extends Activity {
14 |
15 | private ArcAvatarImageView mAvatar;
16 | private ArcFourConnerAvatarImageView mFourAvatar;
17 | private String url = "http://www.baidu.com/img/bdlogo.gif";
18 |
19 | @Override
20 | protected void onCreate(Bundle savedInstanceState) {
21 | super.onCreate(savedInstanceState);
22 | setContentView(R.layout.activity_main);
23 |
24 | mAvatar = (ArcAvatarImageView)findViewById(R.id.avatar);
25 | ImageLoader.getInstance().displayImage(url, mAvatar, ImageLoaderUtils.getDefaultOptions());
26 |
27 | mFourAvatar = (ArcFourConnerAvatarImageView)findViewById(R.id.roundconneravatar);
28 | ImageLoader.getInstance().displayImage(url, mFourAvatar, ImageLoaderUtils.getDefaultOptions());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/com/example/cache/ImageLoaderHandler.java:
--------------------------------------------------------------------------------
1 | package com.example.cache;
2 |
3 | import android.graphics.Bitmap;
4 | import android.os.Bundle;
5 | import android.os.Handler;
6 | import android.os.Message;
7 |
8 | /**
9 | * 线程池中的线程下载完成后的回调Handler基类。
10 | * @author Jack
11 | */
12 | public abstract class ImageLoaderHandler extends Handler {
13 | @Override
14 | public final void handleMessage(Message msg) {
15 | if (msg.what == ImageLoader.HANDLER_MESSAGE_ID) {
16 | Bundle data = msg.getData();
17 | String url = data.getString(ImageLoader.IMAGE_URL_EXTRA);
18 | if (data.getBoolean(ImageLoader.IMAGE_LIMIT_EXTRA, false)) {
19 | handleImageLimited(url);
20 | } else {
21 | Bitmap bitmap = (Bitmap) msg.obj;
22 | handleImageLoaded(url, bitmap);
23 | }
24 | }
25 | else if(msg.what==ImageLoader.HANDLER_MESSAGE_ID1){
26 | handleImagePercent((int)(((double)msg.arg1 / msg.arg2) * 255));
27 | }
28 | }
29 |
30 | protected boolean handleImageLimited(String url) {
31 | return false;
32 | }
33 |
34 | protected abstract boolean handleImageLoaded(String url, Bitmap bitmap);
35 |
36 | protected abstract boolean handleImagePercent(int percent);
37 | }
38 |
--------------------------------------------------------------------------------
/src/com/example/MyApp.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import android.app.Application;
4 | import com.example.cache.ImageLoader;
5 | import com.example.support.ConfigWrapper;
6 | import com.example.utils.BitmapWorkerTask;
7 | import com.example.utils.ImageLoaderUtils;
8 | import com.example.utils.Utils;
9 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
10 |
11 | public class MyApp extends Application {
12 |
13 | public static int screenWidth;
14 | public static int screenHeight;
15 |
16 | @Override
17 | public void onCreate() {
18 |
19 | super.onCreate();
20 | ConfigWrapper.initialize(getApplicationContext());
21 | ImageLoader.initialize(this);
22 | ImageLoader.startConnectivityMonitor(this);
23 | ImageLoader.setThreadPoolSize(10);
24 | ImageLoaderConfiguration config = ImageLoaderUtils
25 | .getApplicationOptions(screenWidth, screenHeight,
26 | getApplicationContext());
27 | // 配置
28 | com.nostra13.universalimageloader.core.ImageLoader.getInstance().init(config);
29 | }
30 |
31 | public void setScreenWH() {
32 | int[] screenHeightAndWidth = Utils
33 | .getScreenHeightAndWidth(getApplicationContext());
34 | screenWidth = screenHeightAndWidth[0];
35 | if (screenWidth <= 480) {
36 | BitmapWorkerTask.getInstance().setMAX_IMAGE_SIZE(false);
37 | }
38 | screenHeight = screenHeightAndWidth[1];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
8 |
9 |
10 |
17 |
18 |
23 |
24 |
25 |
31 |
32 |
37 |
38 |
43 |
44 |
--------------------------------------------------------------------------------
/src/com/example/support/ConfigWrapper.java:
--------------------------------------------------------------------------------
1 | package com.example.support;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | /**
7 | * 对SharedPreferences的封装
8 | * @author Jack
9 | */
10 | public class ConfigWrapper {
11 | private static final String PREF_NAME = "config";
12 |
13 | private static SharedPreferences pref;
14 |
15 | private static SharedPreferences.Editor editor;
16 |
17 | public static void initialize(Context context) {
18 | pref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
19 | editor = pref.edit();
20 | }
21 |
22 | public synchronized static boolean contains(String key) {
23 | return pref.contains(key);
24 | }
25 |
26 | public synchronized static boolean get(String key, boolean defValue) {
27 | return pref.getBoolean(key, defValue);
28 | }
29 |
30 | public synchronized static float get(String key, float defValue) {
31 | return pref.getFloat(key, defValue);
32 | }
33 |
34 | public synchronized static int get(String key, int defValue) {
35 | return pref.getInt(key, defValue);
36 | }
37 |
38 | public synchronized static long get(String key, long defValue) {
39 | return pref.getLong(key, defValue);
40 | }
41 |
42 | public synchronized static String get(String key, String defValue) {
43 | return pref.getString(key, defValue);
44 | }
45 |
46 | public synchronized static void put(String key, boolean value) {
47 | editor.putBoolean(key, value);
48 | }
49 |
50 | public synchronized static void put(String key, float value) {
51 | editor.putFloat(key, value);
52 | }
53 |
54 | public synchronized static void put(String key, int value) {
55 | editor.putInt(key, value);
56 | }
57 |
58 | public synchronized static void put(String key, long value) {
59 | editor.putLong(key, value);
60 | }
61 |
62 | public synchronized static void put(String key, String value) {
63 | editor.putString(key, value);
64 | }
65 |
66 | public synchronized static void commit() {
67 | editor.commit();
68 | }
69 |
70 | public synchronized static void clear() {
71 | editor.clear();
72 | }
73 |
74 | public synchronized static void remove(String key) {
75 | editor.remove(key);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/com/example/cache/MemImageCache.java:
--------------------------------------------------------------------------------
1 | package com.example.cache;
2 |
3 | import java.lang.ref.SoftReference;
4 | import java.util.LinkedHashMap;
5 |
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapFactory;
8 |
9 | /**
10 | * 内存-图片缓存:内存中缓存的是SoftReference,而不是真正的Bitmap
11 | *
12 | * @author Jack
13 | */
14 | public class MemImageCache extends LinkedHashMap>
15 | implements IImageCache {
16 | private static final int DEFAULT_CACHE_CAPACITY = 30;
17 |
18 | private int CACHE_CAPACITY;
19 |
20 | private static final long serialVersionUID = 4687950469523498447L;
21 |
22 | @Override
23 | protected boolean removeEldestEntry(LinkedHashMap.Entry> eldest) {
24 | if (size() > CACHE_CAPACITY) {
25 | return true;
26 | } else
27 | return false;
28 | }
29 |
30 | public MemImageCache() {
31 | this(DEFAULT_CACHE_CAPACITY);
32 | }
33 |
34 | public MemImageCache(int capacity) {
35 | super(capacity / 2, 0.75f, true);
36 | CACHE_CAPACITY = capacity;
37 | }
38 |
39 | @Override
40 | public synchronized Bitmap getBitmap(String url) {
41 | final SoftReference sr = super.get(url);
42 | if (sr != null) {
43 | final Bitmap bitmap = sr.get();
44 | if (null == bitmap) {
45 | remove(url);
46 | } else {
47 | remove(url);
48 | put(url, sr);
49 | return bitmap;
50 | }
51 | }
52 | return null;
53 | }
54 |
55 | @Override
56 | public synchronized boolean putBitmap(String url, Bitmap bitmap) {
57 | put(url, new SoftReference(bitmap));
58 | return true;
59 | }
60 |
61 | @Override
62 | public synchronized boolean putBitmap(String url, byte[] imageData) {
63 | boolean result = false;
64 |
65 | if (imageData != null) {
66 | Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
67 | imageData.length, null);
68 | result = putBitmap(url, bitmap);
69 | }
70 |
71 | return result;
72 | }
73 |
74 | @Override
75 | public synchronized void clearImage() {
76 | super.clear();
77 | }
78 |
79 | @Override
80 | public boolean hasImage(String url) {
81 | return super.containsKey(url);
82 | }
83 |
84 | @Override
85 | public boolean removeImage(String url) {
86 | super.remove(url);
87 | return super.containsKey(url);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/com/example/cache/LocalCache.java:
--------------------------------------------------------------------------------
1 | package com.example.cache;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.Collections;
6 | import java.util.Comparator;
7 | import java.util.List;
8 |
9 | import com.example.utils.BitmapWorkerTask;
10 | import com.example.utils.CommUtils;
11 |
12 | import android.content.Context;
13 |
14 | /**
15 | * 本地缓存
16 | * @author Jack
17 | */
18 | public enum LocalCache {
19 |
20 | /** 图片缓存 */
21 | IMAGE("image", 50 * 1024 * 1024);
22 |
23 | private static File DIR = null;
24 | private String path; // 路径
25 | private StringBuilder localPathSb;
26 | private long maxSize; // 最大大小
27 |
28 | private LocalCache(String name, long maxSize) {
29 | this.path = name;
30 | this.maxSize = maxSize;
31 | }
32 |
33 | public File getPath(Context ctx) {
34 | File dir = new File(getDir(ctx), path);
35 | dir.mkdirs();
36 | return dir;
37 | }
38 |
39 | public String getLocalImgPath(Context ctx, String url) {
40 | if (localPathSb == null) localPathSb = new StringBuilder();
41 | if (DIR == null) getDir(ctx);
42 | synchronized (localPathSb) {
43 | localPathSb.delete(0, localPathSb.length());
44 | localPathSb.append(DIR.getAbsolutePath()).append("/")
45 | .append(CommUtils.getMD5(url));
46 | }
47 | return localPathSb.toString();
48 | }
49 |
50 | /**
51 | * 清空缓存
52 | * @param ctx
53 | */
54 | public static void clear(Context ctx) {
55 | List fileList = fileList(getDir(ctx));
56 | for (File file : fileList) {
57 | file.delete();
58 | }
59 | BitmapWorkerTask.getInstance().clearImageCache();
60 | BitmapWorkerTask.getInstance().clearLoadCache();
61 | }
62 |
63 | /**
64 | * 检查缓存大小
65 | * @param ctx
66 | * @param cachePath
67 | */
68 | public static long checkSize(Context ctx) {
69 | long size = 0;
70 | for (LocalCache cache : values()) {
71 | List fileList = fileList(getDir(ctx));
72 |
73 | //文件最后修改时间排序
74 | Collections.sort(fileList, new Comparator() {
75 | @Override
76 | public int compare(File f1, File f2) {
77 | return (int) (f2.lastModified() - f1.lastModified());
78 | }
79 | });
80 |
81 | for (File file : fileList) {
82 | if (size <= cache.maxSize) {
83 | size += file.length();
84 | } else file.delete();
85 | }
86 | }
87 | return size;
88 | }
89 |
90 | /**
91 | * 获得目录
92 | */
93 | private static File getDir(Context ctx) {
94 | if (DIR != null) return DIR;
95 | DIR = ctx.getCacheDir();
96 | DIR.mkdirs();
97 | return DIR;
98 | }
99 |
100 | /**
101 | * 获得文件列表
102 | */
103 | private static List fileList(File dir) {
104 | List fileList = new ArrayList();
105 | if (dir == null || !dir.canWrite() || !dir.canRead()) return fileList;
106 | if (dir.isFile()) {
107 | fileList.add(dir);
108 | return fileList;
109 | }
110 |
111 | String fileArray[] = dir.list();
112 | for (String name : fileArray) {
113 | File file = new File(dir, name);
114 | if (file.isFile()) fileList.add(file);
115 | else fileList.addAll(fileList(file));//递归
116 | }
117 |
118 | return fileList;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/com/example/widget/WebLimitImageView.java:
--------------------------------------------------------------------------------
1 | package com.example.widget;
2 |
3 | import java.util.Map.Entry;
4 | import java.util.WeakHashMap;
5 |
6 | import android.content.Context;
7 | import android.content.res.TypedArray;
8 | import android.graphics.Bitmap;
9 | import android.graphics.drawable.BitmapDrawable;
10 | import android.text.TextUtils;
11 | import android.util.AttributeSet;
12 | import android.view.View;
13 |
14 | import com.example.android_arcavatarimageview.R;
15 | import com.example.utils.BitmapWorkerTask;
16 | import com.example.utils.BitmapWorkerTask.Callback;
17 | import com.example.utils.Utils;
18 |
19 |
20 |
21 | /**
22 | * 具有二级缓存的、能够限制自动下载的、网络图片ImageView。
23 | * @author Jack
24 | */
25 | public class WebLimitImageView extends WebImageView {
26 |
27 | protected boolean mIsLoadSmallImg = false;
28 | protected final int limit_background;
29 | protected final int limit_background_loading;
30 | protected WeakHashMap mListeners;
31 |
32 | @Override
33 | public boolean isInEditMode() {
34 | return true;
35 | }
36 |
37 | /**
38 | * @param context
39 | */
40 | public WebLimitImageView(Context context) {
41 | this(context, null);
42 | }
43 |
44 | /**
45 | * @param context
46 | * @param attributes
47 | */
48 | public WebLimitImageView(Context context, AttributeSet attrs) {
49 | super(context, attrs);
50 | TypedArray a = context.obtainStyledAttributes(attrs,
51 | R.styleable.WebLimitImageView);
52 | limit_background = a.getResourceId(
53 | R.styleable.WebLimitImageView_limit_background,
54 | android.R.drawable.ic_dialog_info);
55 | limit_background_loading = a.getResourceId(
56 | R.styleable.WebLimitImageView_limit_background_loading,
57 | android.R.drawable.ic_dialog_alert);
58 | a.recycle();
59 | }
60 |
61 | public void setLoadSmallImg(boolean isLoadSmallImg) {
62 | mIsLoadSmallImg = isLoadSmallImg;
63 | }
64 |
65 | /**
66 | * 传入的是本地地址,不要传入网络url地址
67 | * @param path
68 | */
69 | public void loadLocalImage(String path) {
70 | if(path == null || path.length() == 0) return;
71 | Bitmap bitmap = null;
72 | try {
73 | if(mIsLoadSmallImg) {
74 | bitmap = Utils.createSmallBitmap(path);
75 | } else {
76 | bitmap = Utils.create1MBitmap(path);
77 | }
78 | } catch (OutOfMemoryError e) {
79 | e.printStackTrace();
80 | }
81 | if(bitmap != null) {
82 | setImageDrawable(new BitmapDrawable(getResources(), bitmap));
83 | }
84 | }
85 |
86 | /**
87 | * @param url
88 | */
89 | public void loadWebImage(String url) {
90 | mCurrentUrl = url;
91 | Callback callback = new Callback() {
92 |
93 | @Override
94 | public void setImage(View v, Bitmap img, String url) {
95 | if (img != null) {
96 | // 如果是当前View的url
97 | if (!TextUtils.isEmpty(mCurrentUrl) && mCurrentUrl.equalsIgnoreCase(url)) {
98 | setImageDrawable(new BitmapDrawable(getContext().getResources(), img));
99 | } else {
100 | img.recycle();
101 | }
102 | if (mListeners != null && !mListeners.isEmpty()) {
103 | for (Entry entry : mListeners.entrySet()) {
104 | entry.getKey().onImagLoadFinish();
105 | }
106 | }
107 | }
108 | }
109 |
110 | @Override
111 | public boolean isContinue() {
112 | return true;
113 | }
114 |
115 | @Override
116 | public Bitmap formatBitmap(Bitmap img) {
117 | return img;
118 | }
119 | };
120 | loadWebImage(url, callback, true);
121 | }
122 |
123 | /**
124 | * @param url
125 | * @param position ListView中不同位置用于判断同一张图片
126 | * @param callback
127 | * @param isCache
128 | */
129 | public void loadWebImage(String url, Callback callback, boolean isCache) {
130 | BitmapWorkerTask.getInstance().load(this, url, callback, isCache);
131 | }
132 |
133 | public void setOnImageLoadFinish(OnLoadFinish l) {
134 | if (mListeners == null) mListeners = new WeakHashMap();
135 | if (!mListeners.containsKey(l)) mListeners.put(l, "");
136 | }
137 |
138 | public interface OnLoadFinish {
139 | void onImagLoadFinish();
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/com/example/support/ConnectivitySupport.java:
--------------------------------------------------------------------------------
1 | package com.example.support;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Timer;
6 | import java.util.TimerTask;
7 |
8 | import android.content.Context;
9 | import android.net.ConnectivityManager;
10 | import android.net.NetworkInfo;
11 |
12 | /**
13 | * 网络状态监听器,单实例
14 | * @author Jack
15 | * @version 创建时间:2014-3-6 上午9:47:39
16 | */
17 | public class ConnectivitySupport {
18 |
19 | public enum NetState {
20 | NET_NOT_CONNECT, // 没有网落连接
21 |
22 | NET_CONNECT_WIFI, // WIFI
23 |
24 | NET_CONNECT_MOBILE, // MOBILE.3GNET / MOBILE.CMNET / MOBILE.UNINET /
25 | // MOBILE.CTNET / MOBILE.INTERNET
26 |
27 | NET_CONNECT_WAP, // MOBILE.WAP
28 |
29 | NET_CONNECT_UNKNOW, // 未知的网络连接类型
30 | }
31 |
32 | public static final String APN_3G = "3GNET";
33 |
34 | public static final String APN_CMNET = "CMNET";
35 |
36 | public static final String APN_UNINET = "UNINET";
37 |
38 | public static final String APN_CTNET = "CTNET";
39 |
40 | public static final String APN_INTERNET = "INTERNET";
41 |
42 | public static final int DEFAULT_DELAY = 0;
43 |
44 | public static final int DEFAULT_PERIOD = 4 * 1000;
45 |
46 | public static NetState getConnectivityState(Context context) {
47 | NetState net_state = NetState.NET_NOT_CONNECT;
48 | ConnectivityManager connMgr = (ConnectivityManager) context
49 | .getSystemService(Context.CONNECTIVITY_SERVICE);
50 | NetworkInfo netinfo = connMgr.getActiveNetworkInfo();
51 | if (null != netinfo && netinfo.isAvailable() && netinfo.isConnected()) {
52 | int nettype = netinfo.getType();
53 | switch (nettype) {
54 | case ConnectivityManager.TYPE_WIFI:
55 | net_state = NetState.NET_CONNECT_WIFI;
56 | break;
57 | case ConnectivityManager.TYPE_MOBILE:
58 | String extrainfo = netinfo.getExtraInfo();
59 | if (null != extrainfo) {
60 | if (APN_3G.equalsIgnoreCase(extrainfo)
61 | || APN_CMNET.equalsIgnoreCase(extrainfo)
62 | || APN_UNINET.equalsIgnoreCase(extrainfo)
63 | || APN_CTNET.equalsIgnoreCase(extrainfo)
64 | || APN_INTERNET.equalsIgnoreCase(extrainfo)) {
65 | net_state = NetState.NET_CONNECT_MOBILE;
66 | } else {
67 | net_state = NetState.NET_CONNECT_UNKNOW;
68 | }
69 | } else {
70 | net_state = NetState.NET_CONNECT_WAP;
71 | }
72 | break;
73 | default:
74 | net_state = NetState.NET_CONNECT_UNKNOW;
75 | break;
76 | }
77 | } else {
78 | net_state = NetState.NET_NOT_CONNECT;
79 | }
80 | return net_state;
81 | }
82 |
83 | public interface IConnectivityListener {
84 | public void onConnectivityChanged(NetState oldstate, NetState newstate);
85 | }
86 |
87 | private NetState mNetState = NetState.NET_CONNECT_WIFI;
88 |
89 | private Timer mTimer;
90 |
91 | private List mListeners = new ArrayList(
92 | 3);
93 |
94 | private static ConnectivitySupport s_intance;
95 |
96 | private ConnectivitySupport() {
97 | }
98 |
99 | public static ConnectivitySupport getInstance() {
100 | if (null == s_intance) {
101 | s_intance = new ConnectivitySupport();
102 | }
103 | return s_intance;
104 | }
105 |
106 | public NetState getNetState() {
107 | return mNetState;
108 | }
109 |
110 | public void registerConnectivityListener(Context context,
111 | IConnectivityListener listener) {
112 | if (!mListeners.contains(listener)) {
113 | mListeners.add(listener);
114 | if (1 == mListeners.size()) {
115 | mTimer = startConnectivityMonitor(context);
116 | }
117 | }
118 | }
119 |
120 | public void unregisterConnectivityListener(IConnectivityListener listener) {
121 | mListeners.remove(listener);
122 | if (0 == mListeners.size()) {
123 | mTimer.cancel();
124 | }
125 | }
126 |
127 | private Timer startConnectivityMonitor(final Context context) {
128 | Timer timer = new Timer(true);
129 | timer.schedule(new TimerTask() {
130 | @Override
131 | public void run() {
132 | NetState state = getConnectivityState(context);
133 | if (mNetState != state) {
134 | for (IConnectivityListener listener : mListeners) {
135 | listener.onConnectivityChanged(mNetState, state);
136 | }
137 | mNetState = state;
138 | }
139 | }
140 | }, DEFAULT_DELAY, DEFAULT_PERIOD);
141 | return timer;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/com/example/widget/ArcAvatarImageView.java:
--------------------------------------------------------------------------------
1 | package com.example.widget;
2 |
3 | import java.util.Map.Entry;
4 |
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Bitmap;
8 | import android.text.TextUtils;
9 | import android.util.AttributeSet;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 |
13 | import com.example.android_arcavatarimageview.R;
14 | import com.example.cache.ImageLoader;
15 | import com.example.cache.ImageLoaderHandler;
16 | import com.example.utils.BitmapUtils;
17 | import com.example.utils.BitmapWorkerTask.Callback;
18 |
19 | /**
20 | * 圆形头像 继承自WebLimitImageView
21 | * @author Jack
22 | */
23 | public class ArcAvatarImageView extends WebLimitImageView {
24 |
25 | private boolean mIsLoad = false;
26 | private boolean mIsLimit = false;
27 | private final int limit_background;
28 | private final int limit_background_loading;
29 |
30 |
31 | /**
32 | *
33 | * @param context
34 | * @param attrs
35 | */
36 | public ArcAvatarImageView(Context context, AttributeSet attrs) {
37 |
38 | super(context, attrs);
39 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WebLimitImageView);
40 | limit_background = a.getResourceId(R.styleable.WebLimitImageView_limit_background,
41 | android.R.drawable.ic_dialog_info);
42 | limit_background_loading = a.getResourceId(
43 | R.styleable.WebLimitImageView_limit_background_loading,
44 | android.R.drawable.ic_dialog_alert);
45 | a.recycle();
46 | }
47 |
48 | @Override
49 | public void loadWebImage(String url) {
50 | mCurrentUrl = url;
51 | Callback callback = new Callback() {
52 |
53 | @Override
54 | public void setImage(View v, Bitmap img, String url) {
55 | if (img != null) {
56 | // 如果是当前View的url
57 | if (!TextUtils.isEmpty(mCurrentUrl) && mCurrentUrl.equalsIgnoreCase(url)) {
58 | setImageBitmap(BitmapUtils.getRoundCornerImage(img, 5));
59 | } else {
60 | img.recycle();
61 | }
62 | if (mListeners != null && !mListeners.isEmpty()) {
63 | for (Entry entry : mListeners.entrySet()) {
64 | entry.getKey().onImagLoadFinish();
65 | }
66 | }
67 | }
68 | }
69 |
70 | @Override
71 | public boolean isContinue() {
72 | return true;
73 | }
74 |
75 | @Override
76 | public Bitmap formatBitmap(Bitmap img) {
77 | return img;
78 | }
79 | };
80 | loadWebImage(url, callback, true);
81 | }
82 |
83 | private class WebLimitImageViewHandler extends ImageLoaderHandler {
84 | @Override
85 | protected boolean handleImageLoaded(String url, Bitmap bitmap) {
86 | if (url.equalsIgnoreCase(mCurrentUrl)) {
87 | if (null != bitmap) {
88 | setImageBitmap(BitmapUtils.getRoundCornerImage(bitmap, 5));
89 | requestLayout();
90 | invalidate();
91 | mIsLoad = true;
92 | return true;
93 | }
94 | }
95 | return false;
96 | }
97 | @Override
98 | protected boolean handleImageLimited(String url) {
99 | if (url.equalsIgnoreCase(mCurrentUrl)) {
100 | mIsLimit = true;
101 | setImageResource(limit_background);
102 | }
103 | return false;
104 | }
105 | @Override
106 | protected boolean handleImagePercent(int percent) {
107 | return false;
108 | }
109 | }
110 |
111 | /**
112 | * 圆角头像图片显示
113 | */
114 | @Override
115 | public void setImageBitmap(Bitmap bm) {
116 | super.setImageBitmap(BitmapUtils.toRoundBitmap(bm)); //图片圆形显示
117 | }
118 |
119 | /**
120 | * 图片四角带弧度显示
121 | * @param bm
122 | */
123 | public void setImageBitmapRoundConer(Bitmap bm) {
124 | super.setImageBitmap(BitmapUtils.getRoundCornerImage(bm, 5)); //图片四角带弧度显示
125 | }
126 |
127 |
128 | @Override
129 | public boolean onTouchEvent(MotionEvent event) {
130 | if (mIsLimit && !mIsLoad && null != mCurrentUrl) {
131 | switch (event.getAction()) {
132 | case MotionEvent.ACTION_DOWN:
133 | ImageLoader.start(mCurrentUrl, new WebLimitImageViewHandler());
134 | setImageResource(limit_background_loading);
135 | return true;
136 | case MotionEvent.ACTION_CANCEL:
137 | case MotionEvent.ACTION_UP:
138 | case MotionEvent.ACTION_OUTSIDE:
139 | return false;
140 | }
141 | }
142 | return super.onTouchEvent(event);
143 | }
144 | }
--------------------------------------------------------------------------------
/src/com/example/cache/DiskImageCache.java:
--------------------------------------------------------------------------------
1 | package com.example.cache;
2 |
3 | import java.io.BufferedOutputStream;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 |
9 | import android.content.Context;
10 | import android.graphics.Bitmap;
11 | import android.os.Environment;
12 | import android.util.Log;
13 |
14 | import com.example.utils.BitmapUtils;
15 |
16 | /**
17 | * 本地磁盘-图片缓存
18 | * @author Jack
19 | */
20 | public class DiskImageCache implements IImageCache {
21 |
22 | private static String mRootDir;
23 | private static Context mContext;
24 |
25 | public static String getDiskCacheDir() {
26 | return mRootDir;
27 | }
28 |
29 | public DiskImageCache(Context context) {
30 | Context appContext = context.getApplicationContext();
31 | mContext = appContext;
32 |
33 | if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
34 | // SD-card available
35 | mRootDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + appContext.getPackageName() + "/cache";
36 | }
37 | else {
38 | File internalCacheDir = appContext.getCacheDir();
39 | // apparently on some configurations this can come back as null
40 | mRootDir = internalCacheDir.getAbsolutePath();
41 | }
42 |
43 | File outFile = new File(mRootDir);
44 | if (outFile.mkdirs()) {
45 | File nomedia = new File(mRootDir, ".nomedia");
46 | try {
47 | nomedia.createNewFile();
48 | }
49 | catch (IOException e) {
50 | Log.w("l99", e);
51 | }
52 | }
53 | }
54 |
55 | public static String getLocalPathFromUrl(String url) {
56 | String filename = CacheHelper.getFileNameFromUrl(url);
57 | return new StringBuilder(mRootDir).append(File.separator).append(filename).toString();
58 | }
59 |
60 | @Override
61 | public synchronized Bitmap getBitmap(String url) {
62 | Bitmap bitmap = null;
63 | String path = getLocalPathFromUrl(url);
64 | /*
65 | File file = new File(path);
66 | if (file.exists()) {
67 | try {
68 | BitmapFactory.Options opts = new BitmapFactory.Options();
69 | DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
70 | opts.inTargetDensity = metrics.densityDpi;
71 | opts.inScaled = true;
72 |
73 | opts.inDither = false; // Disable Dithering mode
74 | opts.inPurgeable = true; // Tell to gc that whether it needs free memory, the Bitmap can be cleared
75 | opts.inInputShareable = true;
76 |
77 | bitmap = BitmapFactory.decodeFile(path, opts);
78 | } catch (Throwable e) {
79 | Log.w("l99", e);
80 | }
81 | if (null == bitmap) {
82 | Log.e("l99", String.format("Diskcache decode file failed:(url=%s)", url));
83 | file.delete();
84 | }
85 | }
86 | else {
87 | //Log.d("l99", "Disk Cache the file does not exist: " + path);
88 | }
89 | return bitmap;*/
90 | bitmap = BitmapUtils.decodeBitmapFromDescriptor(mContext, path);
91 | return bitmap;
92 | }
93 |
94 | @Override
95 | public synchronized boolean putBitmap(String url, Bitmap bitmap) {
96 | boolean result = false;
97 |
98 | String path = getLocalPathFromUrl(url);
99 | String suffix = CacheHelper.getSuffix(path);
100 |
101 | Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
102 | if (suffix.equalsIgnoreCase(".png")) {
103 | format = Bitmap.CompressFormat.PNG;
104 | }
105 |
106 | try {
107 | FileOutputStream fos = new FileOutputStream(path);
108 | result = bitmap.compress(format, 100, fos);
109 | } catch (FileNotFoundException e) {
110 | Log.w("l99", e);
111 | }
112 |
113 | return result;
114 | }
115 |
116 | @Override
117 | public synchronized boolean putBitmap(String url, byte[] imageData) {
118 | boolean result = false;
119 |
120 | String path = getLocalPathFromUrl(url);
121 | File file = new File(path);
122 | if (file.exists()) {
123 | // file.delete();
124 | result = true;
125 | Log.e("l99", String.format("Diskcache file already exist: url=%s", url));
126 | } else {
127 | try {
128 | file.createNewFile();
129 | BufferedOutputStream ostream = new BufferedOutputStream(new FileOutputStream(file), 8192);
130 | ostream.write(imageData);
131 | ostream.close();
132 |
133 | result = true;
134 | } catch (FileNotFoundException e) {
135 | Log.w("l99", e);
136 | } catch (IOException e) {
137 | Log.w("l99", e);
138 | }
139 | }
140 |
141 | return result;
142 | }
143 |
144 | @Override
145 | public synchronized void clearImage() {
146 | }
147 |
148 | @Override
149 | public synchronized boolean hasImage(String url) {
150 | String path = DiskImageCache.getLocalPathFromUrl(url);
151 | return new File(path).exists();
152 | }
153 |
154 | @Override
155 | public synchronized boolean removeImage(String url) {
156 | boolean result = false;
157 | String path = DiskImageCache.getLocalPathFromUrl(url);
158 | File file = new File(path);
159 | if (file.exists()) {
160 | result = file.delete();
161 | Log.e("l99", String.format("Delete bad image %s: %s.", url, result));
162 | }
163 | return result;
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/com/example/utils/ImageLoaderUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.utils;
2 |
3 | import java.io.File;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.Bitmap.CompressFormat;
7 | import com.example.android_arcavatarimageview.R;
8 | import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
9 | import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
10 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
11 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
12 | import com.nostra13.universalimageloader.core.assist.ImageScaleType;
13 | import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
14 | import com.nostra13.universalimageloader.utils.StorageUtils;
15 |
16 |
17 | /**
18 | * 图片加载配置工具类
19 | * @author Jack
20 | */
21 | public class ImageLoaderUtils {
22 |
23 | public static ImageLoaderConfiguration getApplicationOptions(int width,int height,Context context){
24 | File cacheDir = StorageUtils.getCacheDirectory(context);
25 | ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
26 | // .memoryCacheExtraOptions(width,height)
27 | // .discCacheExtraOptions(width, height, CompressFormat.JPEG, 70, null)
28 | /** 长图保存最大高度为屏幕的屏高*5 **/
29 | .memoryCacheExtraOptions(width, height*5)
30 | // .discCacheExtraOptions(width, height*5, CompressFormat.JPEG, 75, null)
31 | .threadPoolSize(5) // default
32 | // .threadPriority(Thread.NORM_PRIORITY - 1) // default
33 | .tasksProcessingOrder(QueueProcessingType.FIFO) // default
34 | .memoryCache(new LruMemoryCache(4 * 1024 * 1024))
35 | .memoryCacheSize(4 * 1024 * 1024)
36 | .discCache(new UnlimitedDiscCache(cacheDir)) // default
37 | .discCacheSize(50 * 1024 * 1024)
38 | .discCacheFileCount(100)
39 | .writeDebugLogs()
40 | .build();
41 | return config;
42 | }
43 |
44 | public static ImageLoaderConfiguration getMediaLoadOptions(int width,int height,Context context){
45 | File cacheDir = StorageUtils.getCacheDirectory(context);
46 | ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
47 | .memoryCacheExtraOptions(width,height)
48 | .discCacheExtraOptions(width, height, CompressFormat.JPEG, 70, null)
49 | .threadPoolSize(30) // default
50 | // .threadPriority(Thread.NORM_PRIORITY - 1) // default
51 | .tasksProcessingOrder(QueueProcessingType.FIFO) // default
52 | .memoryCache(new LruMemoryCache(4 * 1024 * 1024))
53 | .memoryCacheSize(4 * 1024 * 1024)
54 | .discCache(new UnlimitedDiscCache(cacheDir)) // default
55 | .discCacheSize(50 * 1024 * 1024)
56 | .discCacheFileCount(100)
57 | .writeDebugLogs()
58 | .build();
59 | return config;
60 | }
61 |
62 | /**
63 | * 默认配置
64 | * @return
65 | */
66 | public static DisplayImageOptions getDefaultOptions(){
67 | DisplayImageOptions options = new DisplayImageOptions.Builder()
68 | .cacheInMemory(true)
69 | .cacheOnDisc(true)
70 | .resetViewBeforeLoading(true)
71 | .build();
72 | return options;
73 | }
74 |
75 | /**
76 | * 活动相关
77 | */
78 | public static DisplayImageOptions getActionOptions() {
79 | DisplayImageOptions options = new DisplayImageOptions.Builder()
80 | .cacheInMemory(true)
81 | .cacheOnDisc(true)
82 | .resetViewBeforeLoading(true)
83 | // .showImageForEmptyUri(R.drawable.default_avatar)
84 | // .showImageOnFail(R.drawable.default_avatar)
85 | // .showStubImage(R.drawable.default_avatar)
86 | .imageScaleType(ImageScaleType.EXACTLY)
87 | .build();
88 | return options;
89 | }
90 |
91 | public static DisplayImageOptions getMediaOptions() {
92 | DisplayImageOptions options = new DisplayImageOptions.Builder()
93 | .cacheInMemory(true)
94 | .cacheOnDisc(false)
95 | .bitmapConfig(Bitmap.Config.RGB_565)
96 | .build();
97 | return options;
98 | }
99 |
100 | /**
101 | * 时间轴 单篇文章等使用多张图片的加载
102 | * @return
103 | */
104 | public static DisplayImageOptions getPhotosItemOptions(){
105 | DisplayImageOptions options = new DisplayImageOptions.Builder()
106 | .cacheInMemory(true)
107 | .cacheOnDisc(true)
108 | .build();
109 | return options;
110 | }
111 |
112 |
113 |
114 | /**
115 | * 大学广场、单个大学中图片的加载;
116 | * add by wenqiang 09-04
117 | * @return
118 | */
119 | public static DisplayImageOptions getUniversityItemOptions(){
120 | DisplayImageOptions options = new DisplayImageOptions.Builder()
121 | .cacheInMemory(true)
122 | .cacheOnDisc(true)
123 | .bitmapConfig(Bitmap.Config.RGB_565)
124 |
125 | // .displayer(new FadeInBitmapDisplayer(100))
126 |
127 | // .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
128 | // .imageScaleType(ImageScaleType.EXACTLY)
129 | .build();
130 | return options;
131 | }
132 |
133 | /**
134 | * 个人空间中个性封面图片的加载;
135 | * add by wenqiang 09-07
136 | * @return
137 | */
138 | public static DisplayImageOptions getUserDomainCoverOptions(){
139 | DisplayImageOptions options = new DisplayImageOptions.Builder()
140 | .cacheInMemory(true)
141 | .cacheOnDisc(true)
142 | .bitmapConfig(Bitmap.Config.RGB_565)
143 | // .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
144 | // .imageScaleType(ImageScaleType.EXACTLY)
145 | .build();
146 | return options;
147 | }
148 |
149 | /**
150 | * 默认配置
151 | * @return
152 | */
153 | public static DisplayImageOptions getCircleAvatarOptions(){
154 | DisplayImageOptions options = new DisplayImageOptions.Builder()
155 | // .showImageForEmptyUri(R.drawable.default_avatar)
156 | // .cacheInMemory(true)
157 | // .cacheOnDisc(false)
158 | // .bitmapConfig(Bitmap.Config.RGB_565)
159 | // .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
160 | .build();
161 | return options;
162 | }
163 |
164 | /**
165 | * 活动加载头像
166 | * @return
167 | */
168 | public static DisplayImageOptions getAvactorOptions() {
169 | DisplayImageOptions options = new DisplayImageOptions.Builder()
170 | .cacheInMemory(true)
171 | .cacheOnDisc(true)
172 | .resetViewBeforeLoading(true)
173 | .showImageForEmptyUri(R.drawable.default_round_avatar2)
174 | .showImageOnFail(R.drawable.default_round_avatar2)
175 | // .showStubImage(R.drawable.default_avatar)
176 | // .imageScaleType(ImageScaleType.EXACTLY)
177 | .build();
178 | return options;
179 | }
180 |
181 | }
182 |
--------------------------------------------------------------------------------
/src/com/example/utils/CommUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.utils;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.security.MessageDigest;
9 | import java.security.NoSuchAlgorithmException;
10 |
11 | import android.content.Context;
12 | import android.graphics.Bitmap;
13 | import android.graphics.Bitmap.Config;
14 | import android.graphics.Canvas;
15 | import android.graphics.Paint;
16 | import android.graphics.PorterDuff.Mode;
17 | import android.graphics.PorterDuffXfermode;
18 | import android.graphics.RectF;
19 | import android.net.ConnectivityManager;
20 | import android.net.NetworkInfo;
21 | import android.text.TextUtils;
22 | import android.util.DisplayMetrics;
23 |
24 | public class CommUtils {
25 | public static final String APP_CLIENT_VERSION = "MIGAMEAPP_1.0.0";
26 | /**
27 | * 调试日志的
28 | */
29 | public static final boolean DEBUG = true;
30 |
31 | protected static final int BYTES_IN_MEGA = 1048576;
32 | protected static final int BYTES_IN_KILO = 1024;
33 |
34 | private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5",
35 | "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
36 | /**
37 | * URL 加密密码
38 | */
39 | private static final byte[] URL_KEY = "_&L^W%&*20120724#$U%I)M%I^@"
40 | .getBytes();
41 | private static final byte[] HASH_KEY = "_&W^A%&*20120814#$D%T)M%R^@"
42 | .getBytes();
43 |
44 | /**
45 | * 客户端显示页面的大小
46 | */
47 | public static final String PAGE_SIZE = "15";
48 | public static final int PAGE_COUNT_REQUEST = 15;
49 |
50 | /**
51 | * 获得本地缓存的名字,对url进行hash得到
52 | */
53 | public static final String getCacheFileName(String url) {
54 | return getMD5(url);
55 | }
56 |
57 | public static final String getMD5(String string) {
58 | if (TextUtils.isEmpty(string)) {
59 | return null;
60 | }
61 | MessageDigest digester = null;
62 | try {
63 | digester = MessageDigest.getInstance("MD5");
64 | } catch (NoSuchAlgorithmException e) {
65 | if (CommUtils.DEBUG)
66 | e.printStackTrace();
67 | return null;
68 | }
69 | digester.update(string.getBytes());
70 | byte[] digest = digester.digest();
71 | return byteArrayToString(digest);
72 | }
73 |
74 | public static final String getFileMD5(String filename) {
75 | InputStream fis;
76 | byte[] buffer = new byte[1024];
77 | int numRead = 0;
78 | MessageDigest md5;
79 | try {
80 | fis = new FileInputStream(filename);
81 | } catch (FileNotFoundException e) {
82 | if (CommUtils.DEBUG)
83 | e.printStackTrace();
84 | return null;
85 | }
86 |
87 | try {
88 | md5 = MessageDigest.getInstance("MD5");
89 | while ((numRead = fis.read(buffer)) > 0) {
90 | md5.update(buffer, 0, numRead);
91 | }
92 | } catch (NoSuchAlgorithmException e) {
93 | if (CommUtils.DEBUG)
94 | e.printStackTrace();
95 | return null;
96 | } catch (IOException e) {
97 | if (CommUtils.DEBUG)
98 | e.printStackTrace();
99 | return null;
100 | } finally {
101 | try {
102 | fis.close();
103 | } catch (IOException e) {
104 | if (CommUtils.DEBUG)
105 | e.printStackTrace();
106 | }
107 | }
108 |
109 | return byteArrayToString(md5.digest());
110 | }
111 |
112 | private static String byteArrayToString(byte[] b) {
113 | StringBuffer resultSb = new StringBuffer();
114 | for (int i = 0; i < b.length; i++) {
115 | resultSb.append(byteToHexString(b[i]));
116 | }
117 | return resultSb.toString();
118 | }
119 |
120 | private static String byteToHexString(byte b) {
121 | int n = b;
122 | if (n < 0) {
123 | n = 256 + n;
124 | }
125 | int d1 = n / 16;
126 | int d2 = n % 16;
127 | return hexDigits[d1] + hexDigits[d2];
128 | }
129 |
130 | public static boolean isConnected(Context context) {
131 | if (context == null)
132 | return false;
133 | ConnectivityManager connManager = (ConnectivityManager) context
134 | .getSystemService(Context.CONNECTIVITY_SERVICE);
135 | NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
136 | return networkInfo != null && networkInfo.isConnectedOrConnecting();
137 | }
138 |
139 | public static boolean isWifiConnected(Context context) {
140 | if (null == context)
141 | return false;
142 | ConnectivityManager connManager = (ConnectivityManager) context
143 | .getSystemService(Context.CONNECTIVITY_SERVICE);
144 | NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
145 | return (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI);
146 | }
147 |
148 | public static boolean isMobileConnected(Context context) {
149 | if (null == context)
150 | return false;
151 | ConnectivityManager connManager = (ConnectivityManager) context
152 | .getSystemService(Context.CONNECTIVITY_SERVICE);
153 | NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
154 | return (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
155 | }
156 |
157 | public static boolean isLandscape(Context context) {
158 | if (context == null)
159 | throw new IllegalAccessError("Contex is Null");
160 | DisplayMetrics metrics = context.getResources().getDisplayMetrics();
161 | float widthDp = metrics.widthPixels / metrics.density;
162 | if (widthDp > 480) {
163 | return true;
164 | } else {
165 | return false;
166 | }
167 | }
168 |
169 | public static Bitmap makeRoundImage(Bitmap bm, int rx, int ry) {
170 | if (bm == null) {
171 | return null;
172 | }
173 |
174 | int width = bm.getWidth();
175 | int height = bm.getHeight();
176 | Bitmap round = Bitmap.createBitmap(width, height, Config.ARGB_8888);
177 | Canvas canvas = new Canvas(round);
178 |
179 | final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
180 | int minRound = Math.min(width, height) / 3;
181 | rx = Math.min(rx, minRound);
182 | ry = Math.min(ry, minRound);
183 |
184 | canvas.drawARGB(0, 0, 0, 0);
185 | paint.setColor(0xff424242);
186 | canvas.drawRoundRect(new RectF(0, 0, width, height), rx, ry, paint);
187 |
188 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
189 | canvas.drawBitmap(bm, 0, 0, paint);
190 | bm.recycle();
191 |
192 | return round;
193 | }
194 |
195 | /**
196 | * 数据加密
197 | * @param src
198 | */
199 | public static byte[] encrypt(byte[] src, byte[] pass) {
200 | if (null == src)
201 | return null;
202 | if (null == pass)
203 | return src;
204 | final int srcLen = src.length;
205 | final int passLen = pass.length;
206 | byte[] res = new byte[srcLen];
207 | for (int i = 0; i < srcLen; i += passLen) {
208 | for (int j = 0; j < passLen && (i + j < srcLen); j++) {
209 | res[i + j] = (byte) (src[i + j] ^ pass[j]);
210 | }
211 | }
212 | return res;
213 | }
214 |
215 | /**
216 | * 对URL进行加密
217 | * @param src
218 | * @return
219 | */
220 | public static byte[] encryptUrl(byte[] src) {
221 | return encrypt(src, URL_KEY);
222 | }
223 |
224 | /**
225 | * 对HASH 进行加密
226 | * @return
227 | */
228 | public static byte[] encryptApkHash(byte[] src) {
229 | return encrypt(src, HASH_KEY);
230 | }
231 |
232 | /**
233 | * 删除文件
234 | * @param dir
235 | * @param numDays
236 | * @return
237 | */
238 | public static int clearCacheFolder(File dir, long numDays) {
239 | int deletedFiles = 0;
240 | if (dir != null && dir.isDirectory()) {
241 | try {
242 | for (File child : dir.listFiles()) {
243 | if (child.isDirectory()) {
244 | deletedFiles += clearCacheFolder(child, numDays);
245 | }
246 | if (numDays == 0
247 | || (numDays != 0 && child.lastModified() < numDays)) {
248 | if (child.delete()) {
249 | deletedFiles++;
250 | }
251 | }
252 | }
253 | } catch (Exception e) {
254 | e.printStackTrace();
255 | }
256 | }
257 | return deletedFiles;
258 | }
259 |
260 | public static String getSuffix(String remote) {
261 | int start = remote.lastIndexOf(".");
262 | int end = remote.lastIndexOf("?");
263 | end = (-1 == end || end <= start) ? remote.length() : end;
264 | String suffix = remote.substring(start, end);
265 |
266 | return suffix;
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/src/com/example/support/MediaFile.java:
--------------------------------------------------------------------------------
1 | package com.example.support;
2 |
3 | import java.util.HashMap;
4 | import java.util.Iterator;
5 |
6 |
7 | /**
8 | * 判断媒体文件的具体类型的工具类
9 | * MediaScanner helper class.
10 | * @author Jack
11 | */
12 | public class MediaFile {
13 | // comma separated list of all file extensions supported by the media scanner
14 | public static String sFileExtensions;
15 |
16 | // Audio file types
17 | public static final int FILE_TYPE_MP3 = 1;
18 | public static final int FILE_TYPE_M4A = 2;
19 | public static final int FILE_TYPE_WAV = 3;
20 | public static final int FILE_TYPE_AMR = 4;
21 | public static final int FILE_TYPE_AWB = 5;
22 | public static final int FILE_TYPE_WMA = 6;
23 | public static final int FILE_TYPE_OGG = 7;
24 | private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
25 | private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_OGG;
26 |
27 | // MIDI file types
28 | public static final int FILE_TYPE_MID = 11;
29 | public static final int FILE_TYPE_SMF = 12;
30 | public static final int FILE_TYPE_IMY = 13;
31 | private static final int FIRST_MIDI_FILE_TYPE = FILE_TYPE_MID;
32 | private static final int LAST_MIDI_FILE_TYPE = FILE_TYPE_IMY;
33 |
34 | // Video file types
35 | public static final int FILE_TYPE_MP4 = 21;
36 | public static final int FILE_TYPE_M4V = 22;
37 | public static final int FILE_TYPE_3GPP = 23;
38 | public static final int FILE_TYPE_3GPP2 = 24;
39 | public static final int FILE_TYPE_WMV = 25;
40 | private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4;
41 | private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_WMV;
42 |
43 | // Image file types
44 | public static final int FILE_TYPE_JPEG = 31;
45 | public static final int FILE_TYPE_GIF = 32;
46 | public static final int FILE_TYPE_PNG = 33;
47 | public static final int FILE_TYPE_BMP = 34;
48 | public static final int FILE_TYPE_WBMP = 35;
49 | public static final int FILE_TYPE_BIN = 36;
50 | private static final int FIRST_IMAGE_FILE_TYPE = FILE_TYPE_JPEG;
51 | private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_BIN;
52 |
53 | // Playlist file types
54 | public static final int FILE_TYPE_M3U = 41;
55 | public static final int FILE_TYPE_PLS = 42;
56 | public static final int FILE_TYPE_WPL = 43;
57 | private static final int FIRST_PLAYLIST_FILE_TYPE = FILE_TYPE_M3U;
58 | private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_WPL;
59 |
60 | public static class MediaFileType {
61 | public final int fileType;
62 | public final String mimeType;
63 |
64 | MediaFileType(int fileType, String mimeType) {
65 | this.fileType = fileType;
66 | this.mimeType = mimeType;
67 | }
68 | }
69 |
70 | private static HashMap sFileTypeMap
71 | = new HashMap();
72 | private static HashMap sMimeTypeMap
73 | = new HashMap();
74 |
75 | static void addFileType(String extension, int fileType, String mimeType) {
76 | sFileTypeMap.put(extension, new MediaFileType(fileType, mimeType));
77 | sMimeTypeMap.put(mimeType, Integer.valueOf(fileType));
78 | }
79 |
80 | static {
81 | addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg");
82 | addFileType("M4A", FILE_TYPE_M4A, "audio/mp4");
83 | addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav");
84 | addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
85 | addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb");
86 | addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");
87 | addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
88 |
89 | addFileType("MID", FILE_TYPE_MID, "audio/midi");
90 | addFileType("XMF", FILE_TYPE_MID, "audio/midi");
91 | addFileType("RTTTL", FILE_TYPE_MID, "audio/midi");
92 | addFileType("SMF", FILE_TYPE_SMF, "audio/sp-midi");
93 | addFileType("IMY", FILE_TYPE_IMY, "audio/imelody");
94 |
95 | addFileType("MP4", FILE_TYPE_MP4, "video/mp4");
96 | addFileType("M4V", FILE_TYPE_M4V, "video/mp4");
97 | addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp");
98 | addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp");
99 | addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2");
100 | addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2");
101 | addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");
102 |
103 | addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg");
104 | addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg");
105 | addFileType("GIF", FILE_TYPE_GIF, "image/gif");
106 | addFileType("PNG", FILE_TYPE_PNG, "image/png");
107 | addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp");
108 | addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp");
109 | addFileType("BIN", FILE_TYPE_BIN, "image/bin");
110 |
111 | addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl");
112 | addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls");
113 | addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl");
114 |
115 | // compute file extensions list for native Media Scanner
116 | StringBuilder builder = new StringBuilder();
117 | Iterator iterator = sFileTypeMap.keySet().iterator();
118 |
119 | while (iterator.hasNext()) {
120 | if (builder.length() > 0) {
121 | builder.append(',');
122 | }
123 | builder.append(iterator.next());
124 | }
125 | sFileExtensions = builder.toString();
126 | }
127 |
128 | public static final String UNKNOWN_STRING = "";
129 |
130 | public static boolean isAudioFileType(int fileType) {
131 | return ((fileType >= FIRST_AUDIO_FILE_TYPE &&
132 | fileType <= LAST_AUDIO_FILE_TYPE) ||
133 | (fileType >= FIRST_MIDI_FILE_TYPE &&
134 | fileType <= LAST_MIDI_FILE_TYPE));
135 | }
136 |
137 | public static boolean isVideoFileType(int fileType) {
138 | return (fileType >= FIRST_VIDEO_FILE_TYPE &&
139 | fileType <= LAST_VIDEO_FILE_TYPE);
140 | }
141 |
142 | public static boolean isImageFileType(int fileType) {
143 | return (fileType >= FIRST_IMAGE_FILE_TYPE &&
144 | fileType <= LAST_IMAGE_FILE_TYPE);
145 | }
146 |
147 | public static boolean isGifFileType(int fileType){
148 | return fileType == FILE_TYPE_GIF;
149 | }
150 |
151 | public static boolean isPlayListFileType(int fileType) {
152 | return (fileType >= FIRST_PLAYLIST_FILE_TYPE &&
153 | fileType <= LAST_PLAYLIST_FILE_TYPE);
154 | }
155 |
156 | public static MediaFileType getFileType(String path) {
157 | int lastDot = path.lastIndexOf(".");
158 | if (lastDot < 0)
159 | return null;
160 | return sFileTypeMap.get(path.substring(lastDot + 1).toUpperCase());
161 | }
162 |
163 | /**
164 | * 根据音频文件路径判断文件类型
165 | * @param path
166 | * @return
167 | */
168 | public static boolean isAudioFileType(String path) { //自己增加
169 | MediaFileType type = getFileType(path);
170 | if(null != type) {
171 | return isAudioFileType(type.fileType);
172 | }
173 | return false;
174 | }
175 |
176 | /**
177 | * 根据图片文件路径判断文件类型
178 | * @param path
179 | * @return
180 | */
181 | public static boolean isImageFileType(String path) { //自己增加
182 | MediaFileType type = getFileType(path);
183 | if(null != type) {
184 | return isImageFileType(type.fileType);
185 | }
186 | return false;
187 | }
188 |
189 | public static boolean isGifFileType(String path){
190 | MediaFileType type = getFileType(path);
191 | if(null != type){
192 | return isGifFileType(type.fileType);
193 | }
194 | return false;
195 | }
196 |
197 | /**
198 | * 根据mime类型查看文件类型
199 | * @param mimeType
200 | * @return
201 | */
202 | public static int getFileTypeForMimeType(String mimeType) {
203 | Integer value = sMimeTypeMap.get(mimeType);
204 | return (value == null ? 0 : value.intValue());
205 | }
206 |
207 | }
208 |
--------------------------------------------------------------------------------
/src/com/example/support/SystemSupport.java:
--------------------------------------------------------------------------------
1 | package com.example.support;
2 |
3 | import java.io.File;
4 | import android.app.Activity;
5 | import android.content.ContentResolver;
6 | import android.content.ContentValues;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.database.Cursor;
10 | import android.net.ConnectivityManager;
11 | import android.net.NetworkInfo;
12 | import android.net.Uri;
13 | import android.os.Environment;
14 | import android.os.StatFs;
15 | import android.provider.MediaStore;
16 | import android.provider.MediaStore.Images;
17 | import android.view.View;
18 | import android.view.inputmethod.InputMethodManager;
19 |
20 | /**
21 | * 一些通用的函数,对Android系统的一些操作。
22 | * @author Jack
23 | */
24 | public class SystemSupport {
25 | public static final String MIME_TYPE_EMAIL = "message/rfc822";
26 | public static final String MIME_TYPE_TEXT = "text/*";
27 |
28 | /**
29 | * @param message
30 | */
31 | public static Intent getStartMessageIntent(String message) {
32 | return getStartMessageWithNumberIntent(message, null);
33 | }
34 |
35 | /**
36 | * @param message
37 | * @param number
38 | */
39 | public static Intent getStartMessageWithNumberIntent(String message,
40 | String number) {
41 | Uri uri = null;
42 | if (number != null) {
43 | uri = Uri.parse("smsto:" + number);
44 | } else {
45 | uri = Uri.parse("smsto:");
46 | }
47 | Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
48 | intent.putExtra("sms_body", message);
49 | return intent;
50 | }
51 |
52 | /**
53 | * @param email
54 | * @param subject
55 | * @param message
56 | */
57 | public static Intent getStartEmailIntent(String[] email, String subject,
58 | String body) {
59 | Intent data = new Intent(Intent.ACTION_SENDTO);
60 | data.setData(Uri.parse("mailto: "));
61 | data.putExtra(Intent.EXTRA_SUBJECT, subject);
62 | data.putExtra(Intent.EXTRA_TEXT, body);
63 | return data;
64 | }
65 |
66 | /**
67 | * @param context
68 | * @param req_code
69 | */
70 | public static Intent getStartGalleryIntent() {
71 | Intent intent = new Intent(Intent.ACTION_PICK, null);
72 | intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
73 | return intent;
74 | }
75 |
76 | /**
77 | * @param save_path
78 | * @param file_name
79 | */
80 | public static Intent getStartCameraIntent(File save_file) {
81 | Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
82 | intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(save_file));
83 | return intent;
84 | }
85 |
86 | /**
87 | * @param srcLat
88 | * @param srcLng
89 | * @param tarLat
90 | * @param tarLng
91 | */
92 | public static Intent getStartTraficLineIntent(String srcLat, String srcLng,
93 | String tarLat, String tarLng) {
94 | String url = String
95 | .format("http://ditu.google.cn/maps?f=d&source=s_d&saddr=%s,%s&daddr=%s,%s",
96 | srcLat, srcLng, tarLat, tarLng);
97 | Uri uri = Uri.parse(url);
98 | Intent intent = new Intent(Intent.ACTION_VIEW, uri);
99 | return intent;
100 | }
101 |
102 | /**
103 | * @return
104 | */
105 | public static Intent getStartSecuritySettingsIntent() {
106 | Intent intent = new Intent("android.settings.LOCATION_SOURCE_SETTINGS");
107 | return intent;
108 | }
109 |
110 | public static Intent getInstallApkIntent(String apk) {
111 | Intent intent = new Intent(Intent.ACTION_VIEW);
112 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
113 | intent.setDataAndType(Uri.parse("file://" + apk),
114 | "application/vnd.android.package-archive");
115 | return intent;
116 | }
117 |
118 | /**
119 | * @param context
120 | * @param contentUri
121 | * @return
122 | */
123 | public static String getRealPathFromURI(Context context, Uri contentUri) {
124 | String[] proj = { MediaStore.Images.Media.DATA };
125 | ContentResolver cr = context.getContentResolver();
126 | Cursor cursor = cr.query(contentUri, proj, null, null, null);
127 | String file_name = null;
128 | if (null != cursor && cursor.moveToFirst()) {
129 | try {
130 | int column_index = cursor
131 | .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
132 | file_name = cursor.getString(column_index);
133 | } catch (Exception e) {
134 | e.printStackTrace();
135 | }
136 | } else {
137 | file_name = contentUri.getPath();
138 | }
139 | if (cursor != null)
140 | cursor.close();
141 |
142 | return file_name;
143 | }
144 |
145 | public static boolean saveImage2Gallery(Context context, File file) {
146 | final Uri STORAGE_URI = Images.Media.EXTERNAL_CONTENT_URI;
147 | String IMAGE_MIME_TYPE = "image/png";
148 | ContentValues values = new ContentValues(7);
149 | values.put(Images.Media.TITLE, file.getName());
150 | values.put(Images.Media.DISPLAY_NAME, file.getName());
151 | values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
152 | values.put(Images.Media.MIME_TYPE, IMAGE_MIME_TYPE);
153 | values.put(Images.Media.ORIENTATION, 0);
154 | values.put(Images.Media.DATA, file.getAbsolutePath());
155 | values.put(Images.Media.SIZE, 0);
156 | Uri uri = context.getContentResolver().insert(STORAGE_URI, values);
157 | return null != uri;
158 | }
159 |
160 | /**
161 | *
162 | * // 1.调用显示系统默认的输入法 // 方法一、 InputMethodManager imm = (InputMethodManager)
163 | * getSystemService(Context.INPUT_METHOD_SERVICE);
164 | * imm.showSoftInput(m_receiverView
165 | * (接受软键盘输入的视图(View)),InputMethodManager.SHOW_FORCED
166 | * (提供当前操作的标记,SHOW_FORCED表示强制显示)); // 方法二、 InputMethodManager
167 | * m=(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
168 | * m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
169 | * (这个方法可以实现输入法在窗口上切换显示,如果输入法在窗口上已经显示,则隐藏,如果隐藏,则显示输入法到窗口上)
170 | *
171 | * // 2.调用隐藏系统默认的输入法
172 | * ((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE
173 | * )).hideSoftInputFromWindow
174 | * (WidgetSearchActivity.this.getCurrentFocus().getWindowToken(),
175 | * InputMethodManager.HIDE_NOT_ALWAYS); (WidgetSearchActivity是当前的Activity)
176 | *
177 | * // 3.获取输入法打开的状态 InputMethodManager imm =
178 | * (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
179 | * boolean isOpen=imm.isActive(); // isOpen若返回true,则表示输入法打开
180 | * @param context
181 | */
182 | public static boolean toggleSoftKeyboard(Context context) {
183 | InputMethodManager imm = (InputMethodManager) context
184 | .getSystemService(Activity.INPUT_METHOD_SERVICE);
185 | return imm.isActive();
186 | }
187 |
188 | public static void hideSoftKeyboard(Context context, View v) {
189 | InputMethodManager imm = (InputMethodManager) context
190 | .getSystemService(Activity.INPUT_METHOD_SERVICE);
191 | if (v != null) {
192 |
193 | imm.hideSoftInputFromWindow(v.getApplicationWindowToken(),
194 | InputMethodManager.HIDE_NOT_ALWAYS);
195 | }
196 | }
197 |
198 | public static void showSoftKeyboard(Context context, View v) {
199 | InputMethodManager imm = (InputMethodManager) context
200 | .getSystemService(Activity.INPUT_METHOD_SERVICE);
201 | imm.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT);
202 | imm.showSoftInputFromInputMethod(v.getApplicationWindowToken(),
203 | InputMethodManager.SHOW_IMPLICIT);
204 | }
205 |
206 | public static long readSDCard() {
207 | String state = Environment.getExternalStorageState();
208 | if (Environment.MEDIA_MOUNTED.equals(state)) {
209 | File sdcardDir = Environment.getExternalStorageDirectory();
210 | StatFs sf = new StatFs(sdcardDir.getPath());
211 | long blockSize = sf.getBlockSize();
212 | long availCount = sf.getAvailableBlocks();
213 | return availCount * blockSize / 1024;
214 | } else {
215 | return 0;
216 | }
217 | }
218 |
219 | /**
220 | * 判断是什么网络
221 | * @param ctx
222 | * @return 1移动网络 2wifi 3无网络
223 | */
224 | public static DoveBoxNetState getNetState(Context ctx) {
225 | if (ctx == null)
226 | throw new IllegalAccessError("Context is Null!!!");
227 | ConnectivityManager connManager = (ConnectivityManager) ctx
228 | .getSystemService(Context.CONNECTIVITY_SERVICE);
229 | if (connManager != null) {
230 | NetworkInfo info = connManager.getActiveNetworkInfo();
231 | if (info == null)
232 | return DoveBoxNetState.UNKOWN;
233 | else if (info.getType() == ConnectivityManager.TYPE_MOBILE)
234 | return DoveBoxNetState.MOBILE;
235 | }
236 | return DoveBoxNetState.WIFI;
237 | }
238 |
239 | /**
240 | * 得到网络类型
241 | * 1联通2g 2移动2g 4电信2g
242 | * 5 6 12电信3G 3 8联通3G
243 | *
244 | * @param ctx
245 | * @return
246 | */
247 | public static int getNetMobileType(Context ctx) {
248 | if (ctx != null) {
249 | ConnectivityManager connManager = (ConnectivityManager) ctx
250 | .getSystemService(Context.CONNECTIVITY_SERVICE);
251 | if (connManager != null) {
252 | NetworkInfo info = connManager.getActiveNetworkInfo();
253 | if (info != null
254 | && info.getType() == ConnectivityManager.TYPE_MOBILE) {
255 | return info.getSubtype();
256 | }
257 | }
258 | }
259 | return -1;
260 | }
261 |
262 | public enum DoveBoxNetState {
263 | /**
264 | * 无网络
265 | */
266 | UNKOWN,
267 | /**
268 | * wifi
269 | */
270 | WIFI,
271 | /**
272 | * 移动网络
273 | */
274 | MOBILE;
275 | }
276 | }
277 |
--------------------------------------------------------------------------------
/src/com/example/utils/BitmapUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.utils;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 |
9 | import android.content.Context;
10 | import android.graphics.Bitmap;
11 | import android.graphics.Bitmap.CompressFormat;
12 | import android.graphics.Bitmap.Config;
13 | import android.graphics.BitmapFactory;
14 | import android.graphics.BitmapFactory.Options;
15 | import android.graphics.Canvas;
16 | import android.graphics.Color;
17 | import android.graphics.ColorMatrix;
18 | import android.graphics.ColorMatrixColorFilter;
19 | import android.graphics.Matrix;
20 | import android.graphics.Paint;
21 | import android.graphics.PorterDuff;
22 | import android.graphics.PorterDuff.Mode;
23 | import android.graphics.PorterDuffXfermode;
24 | import android.graphics.Rect;
25 | import android.graphics.RectF;
26 | import android.util.DisplayMetrics;
27 | import android.util.Log;
28 |
29 | /**
30 | * Bitmap处理辅助类
31 | *
32 | * @author Jack
33 | */
34 | public class BitmapUtils {
35 | private static Canvas m_canvas = null;
36 | private static Paint s_paint_eraser = null;
37 | private static Paint s_paint_outline = null;
38 | static {
39 | m_canvas = new Canvas();
40 | s_paint_eraser = new Paint();
41 | s_paint_eraser.setAntiAlias(true);
42 | s_paint_eraser.setDither(true);
43 | s_paint_eraser.setColor(0xFFFFFFFF);
44 | s_paint_eraser.setStrokeWidth(20);
45 | s_paint_eraser.setStyle(Paint.Style.STROKE);
46 | s_paint_eraser.setStrokeJoin(Paint.Join.ROUND);
47 | s_paint_eraser.setStrokeCap(Paint.Cap.ROUND);
48 | s_paint_eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
49 | s_paint_outline = new Paint();
50 | s_paint_outline.setColor(Color.WHITE);
51 | s_paint_outline.setStrokeWidth(20);
52 | }
53 | private static Paint s_paint_gray = null;
54 | static {
55 | s_paint_gray = new Paint();
56 | ColorMatrix matrix = new ColorMatrix();
57 | matrix.setSaturation(0.0f); // 饱和度
58 | ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
59 | s_paint_gray.setColorFilter(filter);
60 | }
61 |
62 | public static Bitmap toGray(Bitmap image) {
63 | Bitmap grayscalBitmap = Bitmap.createBitmap(image.getWidth(),
64 | image.getHeight(), Config.ARGB_4444);
65 | m_canvas.setBitmap(grayscalBitmap);
66 | m_canvas.drawBitmap(image, 0, 0, s_paint_gray);
67 | return grayscalBitmap;
68 | }
69 |
70 | /**
71 | * Returns a new bitmap to be used as the object outline, e.g. to visualize
72 | * the drop location. Responsibility for the bitmap is transferred to the
73 | * caller.
74 | */
75 | public static Bitmap toOutline(Bitmap image) {
76 | Bitmap bitmap1 = Bitmap.createBitmap(image.getWidth(),
77 | image.getHeight(), Bitmap.Config.ARGB_4444);
78 | m_canvas.setBitmap(bitmap1);
79 | // m_canvas.save();
80 | m_canvas.drawBitmap(image, 0, 0, null);
81 | m_canvas.drawBitmap(image, 0, 0, s_paint_eraser);
82 | Bitmap bitmap2 = bitmap1.extractAlpha();
83 | Bitmap bitmap3 = Bitmap.createBitmap(image.getWidth(),
84 | image.getHeight(), Bitmap.Config.ARGB_4444);
85 | m_canvas.setBitmap(bitmap3);
86 | m_canvas.drawBitmap(bitmap2, 0, 0, s_paint_outline);
87 | // m_canvas.restore();
88 | bitmap1.recycle();
89 | bitmap1 = null;
90 | bitmap2.recycle();
91 | bitmap2 = null;
92 | return bitmap3;
93 | }
94 |
95 | public static Bitmap scale(String file, int size, int density) {
96 | Options opts = new Options();
97 | opts.inJustDecodeBounds = true;
98 | BitmapFactory.decodeFile(file, opts);
99 | Log.d("l99", String.format(
100 | "opts.outWidth=%d, opts.outHeight=%d, opts.outMimeType=%s",
101 | opts.outWidth, opts.outHeight, opts.outMimeType));
102 | if (opts.outWidth <= size && opts.outHeight <= size) {
103 | opts.inJustDecodeBounds = false;
104 | return decodeBitmapFromDescriptor(file, opts);
105 | } else {
106 | opts.inScaled = true;
107 | opts.inTargetDensity = density;
108 | opts.inSampleSize = opts.outWidth / size;
109 | opts.inJustDecodeBounds = false;
110 | return decodeBitmapFromDescriptor(file, opts);
111 | }
112 | }
113 |
114 | /**
115 | * 保存图片到指定的路径
116 | * @param bitmap 要保存的bitmap
117 | * @param path 保存到的路径
118 | * @throws IOException IO异常
119 | */
120 | public static void saveBitmap(Bitmap bitmap, String path)
121 | throws IOException {
122 | File file = new File(path);
123 | if (!file.getParentFile().exists())
124 | file.getParentFile().mkdirs();
125 | if (!file.exists()) {
126 | file.createNewFile();
127 | }
128 | FileOutputStream stream = new FileOutputStream(file);
129 | bitmap.compress(CompressFormat.JPEG, 80, stream);
130 | }
131 |
132 | /**
133 | * 利用Matrix旋转图片
134 | * @param bm 需要旋转的图片
135 | * @param degree 旋转角度
136 | * @return 旋转后的图片
137 | */
138 | public static Bitmap rotate(Bitmap bm, int degree) {
139 | Matrix matrix = new Matrix();
140 | matrix.postRotate(degree);
141 | Bitmap bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
142 | bm.getHeight(), matrix, true);
143 | bm.recycle();
144 | return bitmap;
145 | }
146 |
147 | /**
148 | * 根据已有bitmap重新绘制圆角bitmap
149 | * @param bitmap 已有bitmap
150 | * @param roundPixels 圆角半径
151 | * @return
152 | */
153 | public static Bitmap getRoundCornerImage(Bitmap bitmap, int roundPixels) {
154 | Bitmap roundConcerImage = Bitmap.createBitmap(bitmap.getWidth(),
155 | bitmap.getHeight(), Config.ARGB_8888);
156 | Canvas canvas = new Canvas(roundConcerImage);
157 | Paint paint = new Paint();
158 | Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
159 | RectF rectF = new RectF(rect);
160 | paint.setAntiAlias(true);
161 | canvas.drawRoundRect(rectF, roundPixels, roundPixels, paint);
162 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
163 | canvas.drawBitmap(bitmap, null, rect, paint);
164 | return roundConcerImage;
165 | }
166 |
167 | public static Bitmap decodeBitmapFromDescriptor(Context context, String filePath) {
168 | BitmapFactory.Options bfOptions = new BitmapFactory.Options();
169 | DisplayMetrics metrics = context.getResources().getDisplayMetrics();
170 | bfOptions.inTargetDensity = metrics.densityDpi;
171 | bfOptions.inScaled = true;
172 | bfOptions.inDither = false; // Disable Dithering mode
173 | bfOptions.inPurgeable = true; // Tell to gc that whether it needs free memory, the Bitmap can be cleared
174 | bfOptions.inInputShareable = true; // Which kind of reference will be used to recover the Bitmap data
175 | // after being clear, when it will be used in the future
176 | bfOptions.inTempStorage = new byte[12 * 1024];
177 |
178 | File file = new File(filePath);
179 | FileInputStream fs = null;
180 | try {
181 | fs = new FileInputStream(file);
182 | } catch (FileNotFoundException e) {
183 | e.printStackTrace();
184 | }
185 |
186 | if (fs != null) {
187 | try {
188 | return BitmapFactory.decodeFileDescriptor(fs.getFD(), null,
189 | bfOptions);
190 | } catch (IOException e) {
191 | e.printStackTrace();
192 | } finally {
193 | if (fs != null) {
194 | try {
195 | fs.close();
196 | } catch (IOException e) {
197 | e.printStackTrace();
198 | }
199 | }
200 | }
201 | }
202 | return null;
203 | }
204 |
205 | public static Bitmap decodeBitmapFromDescriptor(String filePath, BitmapFactory.Options bfOptions) {
206 | bfOptions.inScaled = true;
207 | bfOptions.inDither = false; // Disable Dithering mode
208 | bfOptions.inPurgeable = true; // Tell to gc that whether it needs free
209 | // memory, the Bitmap can be cleared
210 | bfOptions.inInputShareable = true; // Which kind of reference will be
211 | // used to recover the Bitmap data
212 | // after being clear, when it will
213 | // be used in the future
214 | bfOptions.inTempStorage = new byte[12 * 1024];
215 |
216 | File file = new File(filePath);
217 | FileInputStream fs = null;
218 | try {
219 | fs = new FileInputStream(file);
220 | } catch (FileNotFoundException e) {
221 | e.printStackTrace();
222 | }
223 |
224 | if (fs != null) {
225 | try {
226 | return BitmapFactory.decodeFileDescriptor(fs.getFD(), null,
227 | bfOptions);
228 | } catch (IOException e) {
229 | e.printStackTrace();
230 | } finally {
231 | if (fs != null) {
232 | try {
233 | fs.close();
234 | } catch (IOException e) {
235 | e.printStackTrace();
236 | }
237 | }
238 | }
239 | }
240 | return null;
241 | }
242 |
243 | /**
244 | * 转换图片成圆形
245 | * @param bitmap 传入需要转换的Bitmap对象
246 | * @return 转换后圆形的图片
247 | */
248 | public static Bitmap toRoundBitmap(Bitmap bitmap) {
249 |
250 | int width = bitmap.getWidth();
251 | int height = bitmap.getHeight();
252 | float roundPx;
253 | float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
254 |
255 | if (width <= height) {
256 | roundPx = width / 2;
257 | top = 0;
258 | bottom = width;
259 | left = 0;
260 | right = width;
261 | height = width;
262 | dst_left = 0;
263 | dst_top = 0;
264 | dst_right = width;
265 | dst_bottom = width;
266 | } else {
267 | roundPx = height / 2;
268 | float clip = (width - height) / 2;
269 | left = clip;
270 | right = width - clip;
271 | top = 0;
272 | bottom = height;
273 | width = height;
274 | dst_left = 0;
275 | dst_top = 0;
276 | dst_right = height;
277 | dst_bottom = height;
278 | }
279 |
280 | Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
281 | Canvas canvas = new Canvas(output);
282 | final int color = 0xff424242;
283 | final Paint paint = new Paint();
284 | final Rect src = new Rect((int) left, (int) top, (int) right,
285 | (int) bottom);
286 | final Rect dst = new Rect((int) dst_left, (int) dst_top,
287 | (int) dst_right, (int) dst_bottom);
288 | final RectF rectF = new RectF(dst);
289 | paint.setAntiAlias(true);
290 | canvas.drawARGB(0, 0, 0, 0);
291 | paint.setColor(color);
292 | canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
293 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
294 | canvas.drawBitmap(bitmap, src, dst, paint);
295 | return output;
296 | }
297 | }
298 |
--------------------------------------------------------------------------------
/src/com/example/cache/ImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.example.cache;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.IOException;
5 | import java.net.HttpURLConnection;
6 | import java.net.URL;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 | import java.util.concurrent.ConcurrentHashMap;
10 | import java.util.concurrent.Executors;
11 | import java.util.concurrent.ThreadPoolExecutor;
12 | import android.content.Context;
13 | import android.graphics.Bitmap;
14 | import android.graphics.BitmapFactory;
15 | import android.os.Bundle;
16 | import android.os.Message;
17 | import android.os.SystemClock;
18 | import android.util.DisplayMetrics;
19 | import android.util.Log;
20 | import com.example.support.ConfigWrapper;
21 | import com.example.support.ConnectivitySupport;
22 | import com.example.support.ConnectivitySupport.IConnectivityListener;
23 | import com.example.support.ConnectivitySupport.NetState;
24 |
25 |
26 | /**
27 | * 图片加载类,它封装了一个ThreadPoolExecutor,线程池FixedThreadPool。 它为每一个网络图片启动一个线程,去下载。
28 | * 但当同一张网络图片,被同时load多次时,将对应的handler放入mHandlersCache中,而不是启动多个线程。
29 | * @author Jack
30 | */
31 | public class ImageLoader implements Runnable{
32 |
33 | /**
34 | * The limit ImageLoader code
35 | */
36 | private static final String KEY_LIMIT = "key_limit_webimageview";
37 |
38 | public static int S_LIMIT; // 300K
39 |
40 | // private boolean isNull=false;
41 |
42 | private static ConnectivitySupport s_ConnectivitySupport;
43 |
44 | private static IConnectivityListener s_ConnectivityListener;
45 |
46 | public static void startConnectivityMonitor(Context context) {
47 | setLimit(ConfigWrapper.get(KEY_LIMIT, 300));
48 | s_ConnectivitySupport = ConnectivitySupport.getInstance();
49 | s_ConnectivityListener = new IConnectivityListener() {
50 |
51 | @Override
52 | public void onConnectivityChanged(NetState oldstate,
53 | NetState newstate) {
54 | Log.d("l99", String.format(
55 | "onConnectivityChanged(oldstate=%s, newstate=%s)",
56 | oldstate, newstate));
57 | }
58 | };
59 | s_ConnectivitySupport.registerConnectivityListener(context,
60 | s_ConnectivityListener);
61 | }
62 |
63 | public static void stopConnectivityMonitor() {
64 | s_ConnectivitySupport
65 | .unregisterConnectivityListener(s_ConnectivityListener);
66 | }
67 |
68 | public static void setLimit(int limit) {
69 | S_LIMIT = limit * 1024;
70 |
71 | ConfigWrapper.put(KEY_LIMIT, limit);
72 | ConfigWrapper.commit();
73 | }
74 |
75 | /**
76 | * The original ImageLoader code
77 | */
78 | public static final int HANDLER_MESSAGE_ID1 = 1;
79 | public static final int HANDLER_MESSAGE_ID = 0;
80 | public static final String IMAGE_URL_EXTRA = "imageloader:extra_image_url";
81 | public static final String IMAGE_LIMIT_EXTRA = "imageloader:extra_image_limit";
82 |
83 | private static final int DEFAULT_RETRY_HANDLER_SLEEP_TIME = 1000;
84 | private static final int DEFAULT_NUM_RETRIES = 2;
85 |
86 | // the default thread pool size
87 | private static final int DEFAULT_POOL_SIZE = 6;
88 |
89 | private static ThreadPoolExecutor executor;
90 | private static MemImageCache mMemCache;
91 | private static DiskImageCache mDiskCache;
92 | private static int numRetries = DEFAULT_NUM_RETRIES;
93 |
94 | private static Context mContext;
95 |
96 | // private static ImageLoaderHandler mHandler;
97 |
98 | // private static DownloadListener myListener=null;
99 |
100 | /**
101 | * @param numThreads
102 | * the maximum number of threads that will be started to download
103 | * images in parallel
104 | */
105 | public static void setThreadPoolSize(int numThreads) {
106 | executor.setMaximumPoolSize(numThreads);
107 | }
108 |
109 | /**
110 | * @param numAttempts
111 | * how often the image loader should retry the image download if
112 | * network connection fails
113 | */
114 | public static void setMaxDownloadAttempts(int numAttempts) {
115 | ImageLoader.numRetries = numAttempts;
116 | }
117 |
118 | public static synchronized void initialize(Context context) {
119 | mContext = context.getApplicationContext();
120 | if (executor == null) {
121 | executor = (ThreadPoolExecutor) Executors
122 | .newFixedThreadPool(DEFAULT_POOL_SIZE);
123 | }
124 | if (mMemCache == null) {
125 | mMemCache = new MemImageCache(10);
126 | }
127 | if (mDiskCache == null) {
128 | mDiskCache = new DiskImageCache(context);
129 | }
130 | }
131 |
132 | public static synchronized void clearMemCache() {
133 | if (mMemCache == null) {
134 | mMemCache.clearImage();
135 | }
136 | }
137 |
138 | private static ConcurrentHashMap> mHandlersCache = new ConcurrentHashMap>();
139 | private final String mImageUrl;
140 | private final boolean mImageLimit;
141 | private ImageLoaderHandler mHandler;
142 |
143 | private ImageLoader(ImageLoaderHandler handler, String url, boolean limit) {
144 | mHandler=handler;
145 | mImageUrl = url;
146 | mImageLimit = limit;
147 | }
148 |
149 | public static void start(String imageUrl, ImageLoaderHandler handler) {
150 | start(imageUrl, handler, false);
151 | }
152 |
153 | public static void start(String imageUrl, ImageLoaderHandler handler,
154 | boolean limit) {
155 | // Log.d("l99", String.format("start(%s)", imageUrl));
156 | Bitmap bitmap = mMemCache.getBitmap(imageUrl);
157 | if (null == bitmap) {
158 | List handlers = mHandlersCache.get(imageUrl);
159 | if (null == handlers) {
160 | handlers = new ArrayList(3);
161 | // Log.d("l99",
162 | // String.format("new ArrayList(6):%s",
163 | // imageUrl));
164 | handlers.add(handler);
165 | mHandlersCache.put(imageUrl, handlers);
166 | executor.execute(new ImageLoader(handler, imageUrl, limit));
167 | } else {
168 | handlers.add(handler);
169 | // Log.d("l99", String.format("handlers.add(handler):%s",
170 | // imageUrl));
171 | }
172 | } else {
173 | // do not go through message passing, handle directly instead
174 | handler.handleImageLoaded(imageUrl, bitmap);
175 | }
176 | }
177 |
178 | @Override
179 | public void run() {
180 | DownLoadResult result = null;
181 | Bitmap bitmap = mDiskCache.getBitmap(mImageUrl);
182 | if (null != bitmap) {
183 | result = new DownLoadResult(bitmap, false);
184 | mMemCache.putBitmap(mImageUrl, bitmap);
185 | } else {
186 | result = downloadImage(mHandler);
187 | }
188 | notifyImageLoaded(mImageUrl, result.bitmap, result.limit);
189 | }
190 |
191 | class DownLoadResult {
192 | public final Bitmap bitmap;
193 | public final boolean limit;
194 |
195 | public DownLoadResult(Bitmap bitmap, boolean limit) {
196 | this.bitmap = bitmap;
197 | this.limit = limit;
198 | }
199 | }
200 |
201 | // TODO: we could probably improve performance by re-using connections
202 | // instead of closing them
203 | // after each and every download
204 | protected DownLoadResult downloadImage(ImageLoaderHandler handler) {
205 | boolean save_image = true;
206 | int timesTried = 1;
207 | Bitmap bitmap = null;
208 | boolean limit = false;
209 | while (timesTried <= numRetries) {
210 | try {
211 | URL url = new URL(mImageUrl);
212 | HttpURLConnection connection = (HttpURLConnection) url.openConnection();
213 |
214 | int fileSize = getContentLength(connection);
215 | if (fileSize < 0) {
216 | Log.e("l99", String.format("downloadImage(fileSize=%d): %s", fileSize,mImageUrl));
217 | } else {
218 | if (mImageLimit&& NetState.NET_CONNECT_MOBILE == s_ConnectivitySupport.getNetState() && fileSize > S_LIMIT) {
219 | limit = true;
220 | connection.disconnect();
221 | break;
222 | } else {
223 | byte[] imageData = retrieveImageData(handler,connection,fileSize);
224 | connection.disconnect();
225 | if (imageData != null) {
226 | BitmapFactory.Options opts = new BitmapFactory.Options();
227 | DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
228 | opts.inTargetDensity = metrics.densityDpi;
229 | opts.inScaled = true;
230 | opts.inDither = false; // Disable Dithering mode
231 | opts.inPurgeable = true; // Tell to gc that whether
232 | // it needs free memory,
233 | // the Bitmap can be
234 | // cleared
235 | opts.inInputShareable = true;
236 |
237 | bitmap = BitmapFactory.decodeByteArray(imageData,0, imageData.length, opts);
238 | mMemCache.putBitmap(mImageUrl, bitmap);
239 | save_image = mDiskCache.putBitmap(mImageUrl,imageData);
240 |
241 | break;
242 | }
243 | }
244 | }
245 | } catch (Throwable e) {
246 | Log.w("l99", e);
247 | } finally {
248 | SystemClock.sleep(DEFAULT_RETRY_HANDLER_SLEEP_TIME);
249 | timesTried++;
250 | }
251 | }
252 |
253 | if (!save_image) {
254 | mDiskCache.removeImage(mImageUrl);
255 | }
256 | return new DownLoadResult(bitmap, limit);
257 | }
258 |
259 | public static boolean isCached(String imageUrl) {
260 | return mDiskCache.hasImage(imageUrl);
261 | }
262 |
263 | protected int getContentLength(HttpURLConnection connection) {
264 | // determine the image size and allocate a buffer
265 | int fileSize = connection.getContentLength();
266 | return fileSize;
267 | }
268 |
269 | protected byte[] retrieveImageData(ImageLoaderHandler handler,HttpURLConnection connection,int fileSize) throws IOException {
270 | byte[] imageData = new byte[fileSize];
271 |
272 | handler.sendMessage(handler.obtainMessage(ImageLoader.HANDLER_MESSAGE_ID1, 0, fileSize));
273 | // download the file
274 | BufferedInputStream istream = new BufferedInputStream(connection.getInputStream(), 8192);
275 | int bytesRead = 0;
276 | int offset = 0;
277 | while (bytesRead != -1 && offset < fileSize) {
278 | bytesRead = istream.read(imageData, offset, fileSize - offset);
279 | offset += bytesRead;
280 |
281 | handler.sendMessage(handler.obtainMessage(ImageLoader.HANDLER_MESSAGE_ID1, offset, fileSize));
282 |
283 | }
284 |
285 | handler.sendMessage(handler.obtainMessage(ImageLoader.HANDLER_MESSAGE_ID1, fileSize, fileSize));
286 | // clean up
287 | istream.close();
288 | return imageData;
289 | }
290 |
291 | public void notifyImageLoaded(String url, Bitmap bitmap, boolean limit) {
292 | List handlers = mHandlersCache.remove(url);
293 | // Log.i("l99", String.format("notifyImageLoaded(%d):limit=%s, %s",
294 | // handlers.size(), limit, mImageUrl));
295 | for (ImageLoaderHandler handler : handlers) {
296 | Message message = Message.obtain();
297 | message.what = HANDLER_MESSAGE_ID;
298 |
299 | Bundle data = new Bundle();
300 | data.putString(IMAGE_URL_EXTRA, url);
301 | data.putBoolean(IMAGE_LIMIT_EXTRA, limit);
302 | message.setData(data);
303 |
304 | message.obj = bitmap;
305 |
306 | handler.sendMessage(message);
307 | }
308 | }
309 | }
310 |
--------------------------------------------------------------------------------
/src/com/example/utils/BitmapWorkerTask.java:
--------------------------------------------------------------------------------
1 | package com.example.utils;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedOutputStream;
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.File;
7 | import java.io.FileOutputStream;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.net.MalformedURLException;
11 | import java.net.URL;
12 | import java.util.Collections;
13 | import java.util.Iterator;
14 | import java.util.Map;
15 | import java.util.Map.Entry;
16 | import java.util.WeakHashMap;
17 | import java.util.concurrent.ExecutorService;
18 | import java.util.concurrent.Executors;
19 |
20 | import android.content.Context;
21 | import android.graphics.Bitmap;
22 | import android.graphics.BitmapFactory;
23 | import android.graphics.BitmapFactory.Options;
24 | import android.os.Handler;
25 | import android.os.Message;
26 | import android.text.TextUtils;
27 | import android.view.View;
28 | import android.widget.ImageSwitcher;
29 |
30 | import com.example.cache.LocalCache;
31 | import com.example.support.MediaFile;
32 |
33 |
34 | /**
35 | * 图片加载
36 | * @author Jack
37 | */
38 | public class BitmapWorkerTask {
39 | // 大于16M的图片降低图片清晰度
40 | private static int MAX_IMAGE_SIZE = 16 * 1024 * 1024;
41 | public static final int BUFF_SIZE = 1024 * 8;
42 | private static final int _1M = 1024 * 1024;
43 |
44 | private static ExecutorService EXECUTOR = null;
45 | private static BitmapWorkerTask mInstance;
46 | private Map mImageCache;
47 | // 用于判断是否正在加载
48 | private Map mLoadCache;
49 |
50 | /**
51 | * 如果是小于480的屏宽设置最大图片未6M
52 | * @param isBigScreen 是否大于480
53 | */
54 | public void setMAX_IMAGE_SIZE(boolean isBigScreen) {
55 | if (!isBigScreen) {
56 | MAX_IMAGE_SIZE = 8 * 1024 * 1024;
57 | }
58 | }
59 |
60 | public void clearImageCache(Bitmap bitmap){
61 | if (bitmap == null) return;
62 | if (mImageCache != null && mImageCache.size() > 0) {
63 | mImageCache.remove(bitmap);
64 | }
65 | }
66 |
67 | public void clearImageCache() {
68 | if (mImageCache != null && !mImageCache.isEmpty()) {
69 | mImageCache.clear();
70 | }
71 | }
72 |
73 | public void clearLoadCache() {
74 | if (mLoadCache != null && !mLoadCache.isEmpty()) {
75 | mLoadCache.clear();
76 | }
77 | }
78 |
79 | public static BitmapWorkerTask getInstance() {
80 | if (mInstance == null) {
81 | mInstance = new BitmapWorkerTask();
82 | }
83 |
84 | if (EXECUTOR == null) {
85 | EXECUTOR = Executors.newFixedThreadPool(6);
86 | }
87 | return mInstance;
88 | }
89 |
90 | private BitmapWorkerTask() {}
91 |
92 | /*
93 | * 加载任务
94 | */
95 | class Task extends Handler implements Runnable {
96 | int width, height;
97 | View view = null;
98 | String url = null;
99 | boolean isCache = true;
100 | boolean isProcessLocal = false;
101 | BitmapWorkerTask.Callback callback = null;
102 |
103 | @Override
104 | public void run() {
105 | Bitmap bitmap = null;
106 | byte[] data = null;
107 | if (callback.isContinue() && !TextUtils.isEmpty(url)) {
108 | bitmap = loadLoaclCache(view.getContext(), url, callback, isProcessLocal);
109 | if (!isProcessLocal && bitmap == null) {
110 | URL m = null;
111 | InputStream in = null;
112 | BufferedInputStream bis = null;
113 | ByteArrayOutputStream out = null;
114 | try {
115 | m = new URL(url);
116 | in = (InputStream) m.getContent();
117 | if (!callback.isContinue()) return;
118 | if (in != null) {
119 | bis = new BufferedInputStream(in, BUFF_SIZE);
120 | out = new ByteArrayOutputStream();
121 | int len = 0;
122 | byte[] buffer = new byte[1024];
123 | while ((len = bis.read(buffer)) != -1) {
124 | out.write(buffer, 0, len);
125 | out.flush();
126 | }
127 | data = out.toByteArray();
128 | if (!callback.isContinue()) return;
129 | Options opts = new Options();
130 | opts.inJustDecodeBounds = true;
131 | BitmapFactory.decodeByteArray(data, 0, data.length, opts);
132 | if (opts.outWidth * opts.outHeight * 4 >= MAX_IMAGE_SIZE) {
133 | opts.inPreferredConfig = Bitmap.Config.ARGB_4444;
134 | }
135 | opts.inJustDecodeBounds = false;
136 | if (width <= 0 && height <= 0) bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
137 | else bitmap = processBitMap(data, width, height);
138 | if (bitmap != null) {
139 | bitmap = callback.formatBitmap(bitmap);
140 | saveLoaclCache(view.getContext(), url, data, bitmap);
141 | }
142 | }
143 | } catch (MalformedURLException e) {
144 | e.printStackTrace();
145 | } catch (IOException e) {
146 | e.printStackTrace();
147 | } finally {
148 | try {
149 | if (in != null) in.close();
150 | if (out != null) out.close();
151 | if (bis != null) bis.close();
152 | if (mLoadCache != null) mLoadCache.remove(url);
153 | } catch (Exception e) {
154 | e.printStackTrace();
155 | }
156 | }
157 | }
158 | }
159 | obtainMessage(513, bitmap).sendToTarget();
160 | }
161 |
162 | @Override
163 | public void handleMessage(Message msg) {
164 | if (isCache && msg.obj != null) {
165 | if (mImageCache == null) mImageCache = Collections.synchronizedMap(new WeakHashMap());
166 | mImageCache.put((Bitmap) msg.obj, url);
167 | }
168 | callback.setImage(view, (Bitmap) msg.obj, url);// 设置加载完成
169 | }
170 | }
171 |
172 | /**
173 | * 根据参数宽高获取Bitmap
174 | * @param data
175 | * @param height
176 | * @param width
177 | * @return
178 | */
179 | private Bitmap processBitMap(byte[] data, int width, int height) {
180 | Options options = new BitmapFactory.Options();
181 | options.inJustDecodeBounds = true;
182 | BitmapFactory.decodeByteArray(data, 0, data.length, options);
183 | // Calculate inSampleSize
184 | options.inSampleSize = (int) Math.ceil(Math.sqrt(options.outWidth * options.outHeight * 4 / _1M ) );
185 | // Decode bitmap with inSampleSize set
186 | options.inJustDecodeBounds = false;
187 |
188 | return BitmapFactory.decodeByteArray(data, 0, data.length, options);
189 | }
190 |
191 | /**
192 | * 执行下一个任务
193 | * @param task
194 | */
195 | private void startNextTask(Task task) {
196 | try {
197 | EXECUTOR.submit(task);
198 | } catch (Exception e) {
199 | e.printStackTrace();
200 | }
201 | }
202 |
203 | /**
204 | * 带图片参数的加载图片
205 | * @param view
206 | * @param url
207 | * @param callback
208 | * @param width
209 | * @param height
210 | * @param isCache 是否缓存到内存
211 | */
212 | public void loadWithSize(View view, String url, Callback callback, int width, int height, boolean isCache){
213 | if (!check(view, url, callback))
214 | return;
215 | loadStart(view, url, callback, width, height, isCache, false);
216 | }
217 |
218 | /**
219 | * 使用ImageSwitcher加载图片
220 | * @param view
221 | * @param url
222 | * @param callback
223 | * @param isCache 是否缓存到内存
224 | */
225 | public void loadWithImageSwitcher(ImageSwitcher view, String url, Callback callback, boolean isCache){
226 | if (!check(view, url, callback)) return;
227 |
228 | loadStart(view, url, callback, 0, 0, isCache, false);
229 | }
230 |
231 | /**
232 | * 加载图片
233 | * @param view
234 | * @param url
235 | * @param callback
236 | * @param isCache 是否缓存到内存
237 | */
238 | public void load(View view, String url, BitmapWorkerTask.Callback callback, boolean isCache) {
239 | if (!check(view, url, callback))
240 | return;
241 |
242 | loadStart(view, url, callback, 0, 0, isCache, false);
243 | }
244 |
245 | /**
246 | * @param view
247 | * @param url
248 | * @param callback
249 | * @param isProcessLocal 是否处理本地图片
250 | */
251 | public void loadLocalFileCallback(View view, String url, BitmapWorkerTask.Callback callback, boolean isProcessLocal) {
252 | if (!check(view, url, callback))
253 | return;
254 |
255 | loadStart(view, url, callback, 0, 0, true, isProcessLocal);
256 | }
257 |
258 | /**
259 | * 开始加载
260 | * @param view
261 | * @param url
262 | * @param callback
263 | * @param width
264 | * @param height
265 | * @param isCache 是否缓存到内存
266 | * @param isProcessLocal 是否处理本地图片
267 | */
268 | private void loadStart(View view, String url, BitmapWorkerTask.Callback callback,
269 | int width, int height, boolean isCache, boolean isProcessLocal) {
270 | if (isCache && mImageCache != null && !mImageCache.isEmpty()) {
271 | Iterator> iterator = mImageCache.entrySet().iterator();
272 | while (iterator.hasNext()) {
273 | Entry entry = iterator.next();
274 | if (url.equals(entry.getValue())) {
275 | if (entry.getKey() != null && !entry.getKey().isRecycled()) {
276 | callback.setImage(view, entry.getKey(), url); // 直接返回
277 | return;
278 | } else {
279 | mImageCache.remove(entry.getKey());
280 | break;
281 | }
282 | }
283 | }
284 | }
285 | if (mLoadCache == null) mLoadCache = Collections.synchronizedMap(new WeakHashMap());
286 | // 如果正在加载返回(还未下载成功)
287 | if (!isProcessLocal && mLoadCache.containsKey(url)) {
288 | File file = localFile(view.getContext(), url);
289 | if (file == null || !file.exists()) {
290 | return;
291 | }
292 | }
293 |
294 | mLoadCache.put(url, "");
295 | startNextTask(createTask(view, url, callback, width, height, isCache, isProcessLocal));
296 | }
297 |
298 | /**
299 | * 创建任务
300 | * @param view
301 | * @param url
302 | * @param callback
303 | * @param width
304 | * @param height
305 | * @param isCache 是否缓存到内存
306 | * @param processLocal 是否处理本地图片
307 | * @return
308 | */
309 | private Task createTask(View view, String url,
310 | BitmapWorkerTask.Callback callback, int width, int height, boolean isCache, boolean processLocal) {
311 | Task task = new Task();
312 | task.callback = callback;
313 | task.view = view;
314 | task.url = url;
315 | task.width = width;
316 | task.height = height;
317 | task.isCache = isCache;
318 | task.isProcessLocal = processLocal;
319 | return task;
320 | }
321 |
322 | /**
323 | * 是否通过检查
324 | * @param view
325 | * @param url
326 | * @param callback
327 | * @return
328 | */
329 | private boolean check(View view, String url, BitmapWorkerTask.Callback callback) {
330 | if (view == null)
331 | return false;
332 | if (TextUtils.isEmpty(url))
333 | return false;
334 | if (callback == null)
335 | return false;
336 | return true;
337 | }
338 |
339 | /**
340 | * 加载本地缓存
341 | * @param ctx
342 | * @param url
343 | * @param callback
344 | * @param isProcessLocal
345 | * @return
346 | */
347 | private synchronized Bitmap loadLoaclCache(Context ctx, String url, Callback callback, boolean isProcessLocal) {
348 | // 是否处理本地图片
349 | if (!isProcessLocal) {
350 | File file = localFile(ctx, url);
351 | if (file != null && file.exists() && file.canRead()) {
352 | try {
353 | Options opts = new Options();
354 | opts.inJustDecodeBounds = true;
355 | BitmapFactory.decodeFile(file.getPath(), opts);
356 | if (opts.outWidth * opts.outHeight * 4 >= MAX_IMAGE_SIZE) {
357 | opts.inPreferredConfig = Bitmap.Config.ARGB_4444;
358 | }
359 | opts.inJustDecodeBounds = false;
360 | return BitmapUtils.decodeBitmapFromDescriptor(file.getPath(), opts);
361 | } catch (OutOfMemoryError e1) {
362 | } catch (Exception e) {
363 | }
364 | }
365 | } else {
366 | return callback.formatBitmap(null);
367 | }
368 | return null;
369 | }
370 |
371 | private File localFile(Context ctx, String url) {
372 | if (ctx == null || TextUtils.isEmpty(url))
373 | return null;
374 | File file = new File(LocalCache.IMAGE.getLocalImgPath(ctx, url));
375 | return file;
376 | }
377 |
378 | /**
379 | * 保存本地缓存
380 | * @param context
381 | * @param url
382 | * @param buffer
383 | * @param img
384 | */
385 | private synchronized void saveLoaclCache(Context ctx, String url, byte[] buffer, Bitmap img) {
386 | if (buffer == null)
387 | return;
388 | File file = localFile(ctx, url);
389 | deleteFile(file);
390 | FileOutputStream fos = null;
391 | try {
392 | if (MediaFile.isGifFileType(url)) {
393 | fos = new FileOutputStream(file);
394 | BufferedOutputStream bos = new BufferedOutputStream(fos, BUFF_SIZE);
395 | if (bos != null) {
396 | bos.write(buffer);
397 | bos.flush();
398 | bos.close();
399 | }
400 | } else {
401 | fos = new FileOutputStream(file);
402 | img.compress(Bitmap.CompressFormat.PNG, 100, fos);
403 | }
404 | } catch (Exception e) {
405 | e.printStackTrace();
406 | deleteFile(file);
407 | } finally {
408 | try {
409 | if (fos != null) fos.close();
410 | } catch (IOException e) {
411 | e.printStackTrace();
412 | deleteFile(file);
413 | }
414 | }
415 | }
416 |
417 | private void deleteFile(File file) {
418 | if (file != null && file.exists() && file.canWrite()) {
419 | file.delete();
420 | }
421 | }
422 |
423 | /**
424 | * 加载回调
425 | * @author Mike
426 | */
427 | public interface Callback {
428 | /**
429 | * 格式化图片
430 | * @param img
431 | * @return img
432 | */
433 | public Bitmap formatBitmap(Bitmap img);
434 |
435 | /**
436 | * 使用图片
437 | * @param View
438 | * @param img
439 | */
440 | public void setImage(View v, Bitmap img, String url);
441 |
442 | /**
443 | * 当前任务是否继续
444 | * @return
445 | */
446 | public boolean isContinue();
447 | }
448 | }
449 |
--------------------------------------------------------------------------------
/src/com/example/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package com.example.utils;
2 |
3 | import java.io.BufferedOutputStream;
4 | import java.io.BufferedReader;
5 | import java.io.ByteArrayInputStream;
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.Closeable;
8 | import java.io.File;
9 | import java.io.FileInputStream;
10 | import java.io.FileOutputStream;
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.io.InputStreamReader;
14 | import java.io.ObjectInputStream;
15 | import java.io.ObjectOutputStream;
16 | import java.io.OutputStream;
17 | import java.io.UnsupportedEncodingException;
18 | import java.net.URLEncoder;
19 | import java.nio.channels.FileChannel;
20 | import java.text.ParseException;
21 | import java.text.SimpleDateFormat;
22 | import java.util.Date;
23 | import java.util.Locale;
24 | import java.util.Set;
25 | import java.util.UUID;
26 |
27 | import android.content.Context;
28 | import android.graphics.Bitmap;
29 | import android.graphics.Bitmap.Config;
30 | import android.graphics.BitmapFactory;
31 | import android.graphics.BitmapFactory.Options;
32 | import android.graphics.Matrix;
33 | import android.os.Bundle;
34 | import android.os.Environment;
35 | import android.text.TextUtils;
36 | import android.util.DisplayMetrics;
37 | import android.util.Log;
38 |
39 | import com.example.android_arcavatarimageview.R;
40 | import com.example.support.SystemSupport;
41 |
42 |
43 | /**
44 | * 一些通用的方法
45 | * @author Jack
46 | */
47 | public class Utils {
48 |
49 | /**
50 | * The number of bytes in a kilobyte.
51 | */
52 | public static final long ONE_KB = 1024;
53 |
54 | /**
55 | * The number of bytes in a megabyte.
56 | */
57 | public static final long ONE_MB = ONE_KB * ONE_KB;
58 |
59 | /**
60 | * The file copy buffer size (30 MB)
61 | */
62 | private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30;
63 |
64 | protected static SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("MM/dd HH:mm");
65 | protected static SimpleDateFormat mSimpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
66 | public static final int MEDIA_TYPE_VIDEO_THUMBNAIL = 1; //视频缩略图
67 | public static final int MEDIA_TYPE_VIDEO = 2; //视频
68 | public static final int MEDIA_TYPE_ZIP = 3; //视频
69 |
70 | public static void chmod(String permission, String path) {
71 | try {
72 | String command = "chmod " + permission + " " + path;
73 | Runtime runtime = Runtime.getRuntime();
74 | runtime.exec(command);
75 | } catch (IOException e) {
76 | e.printStackTrace();
77 | }
78 | }
79 |
80 | /**
81 | *
82 | * @param is
83 | * @return
84 | * @throws IOException
85 | */
86 | public static String streamToString(InputStream is) {
87 | return streamToString(is, "UTF-8");
88 | }
89 |
90 | public static String streamToString(InputStream is, String enc) {
91 | StringBuilder buffer = new StringBuilder();
92 | String line = null;
93 | try {
94 | BufferedReader reader = new BufferedReader(new InputStreamReader(is, enc), 8192);
95 | while (null != (line = reader.readLine())) {
96 | buffer.append(line);
97 | }
98 | } catch (Exception e) {
99 | e.printStackTrace();
100 | } finally {
101 | try {
102 | is.close();
103 | } catch (IOException e) {
104 | e.printStackTrace();
105 | }
106 | }
107 | return buffer.toString();
108 | }
109 |
110 | /**
111 | * @param is
112 | * @param os
113 | */
114 | public static void copyStream(InputStream is, OutputStream os) {
115 | final int buffer_size = 1024;
116 | try {
117 | byte[] bytes = new byte[buffer_size];
118 | int count = is.read(bytes, 0, buffer_size);
119 | while (-1 != count) {
120 | os.write(bytes, 0, count);
121 | count = is.read(bytes, 0, buffer_size);
122 | }
123 | } catch (Exception ex) {
124 | ex.printStackTrace();
125 | }
126 | }
127 |
128 | public static String bundle2String(Bundle bundle) throws UnsupportedEncodingException {
129 | if (null != bundle) {
130 | Set keys = bundle.keySet();
131 | if (null != keys && !keys.isEmpty()) {
132 | StringBuilder buffer = new StringBuilder();
133 | for (String key : keys) {
134 | String value = bundle.getString(key);
135 | buffer.append("&").append(key).append("=").append(URLEncoder.encode(value, "UTF-8"));
136 | }
137 | return buffer.toString();
138 | }
139 | }
140 |
141 | return "";
142 | }
143 |
144 | /**
145 | * px(value)=(int) (dip(value) * density + 0.5)
146 | *
147 | * @param context
148 | * @param dipValue
149 | * @return
150 | */
151 | public static int dip2px(Context context, float dipValue) {
152 | final float density = context.getResources().getDisplayMetrics().density;
153 | return (int) (dipValue * density + 0.5f);
154 | }
155 |
156 | /**
157 | * dip(value)=(int) (px(value) / density + 0.5)
158 | *
159 | * @param context
160 | * @param pxValue
161 | * @return
162 | */
163 | public static int px2dip(Context context, float pxValue) {
164 | final float density = context.getResources().getDisplayMetrics().density;
165 | return (int) (pxValue / density + 0.5f);
166 | }
167 |
168 | public static int dip2DeviceWidthPx(Context context, float dipValue) {
169 | final float density = context.getResources().getDisplayMetrics().density;
170 | float widthPixels = context.getResources().getDisplayMetrics().widthPixels;
171 | return (int) (widthPixels - density * 320 + density * dipValue);
172 | }
173 |
174 | /**
175 | * @param date
176 | * @return
177 | */
178 | public static String getDisplayTime(Long date) {
179 | return new SimpleDateFormat("MM/dd HH:mm").format(date);
180 | }
181 |
182 | /**
183 | * @param date
184 | * @return
185 | */
186 | public static String getDisplayTime2(Long date) {
187 | return new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date);
188 | }
189 |
190 | /**
191 | * 转换UTC时间
192 | *
193 | * @param utcTime
194 | * @return
195 | */
196 | public static Date getDateByUTC(String utcTime) {
197 | Date date;
198 | SimpleDateFormat formatter = new SimpleDateFormat("E MMM dd HH:mm:ss ZZZZ yyyy", Locale.ENGLISH);
199 |
200 | try {
201 | date = formatter.parse(utcTime);
202 | } catch (ParseException e) {
203 | e.printStackTrace();
204 | date = new Date();
205 | }
206 |
207 | return date;
208 | }
209 |
210 | public static String getDateStringByUTC(String utcTime) {
211 | if (TextUtils.isEmpty(utcTime)) return "";
212 | return mSimpleDateFormat.format(new Date(utcTime));
213 | }
214 |
215 | public static String getDateStringByUTC2(String utcTime) {
216 | String timeStr = null;
217 | if (utcTime != null) {
218 | timeStr = mSimpleDateFormat2.format(new Date(utcTime));
219 | }
220 | return timeStr;
221 | }
222 |
223 | public static String getVideoTimeFormatString(int currentPosition, int duration) {
224 | SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
225 | StringBuffer resultStr = new StringBuffer();
226 | resultStr.append(formatter.format(currentPosition));
227 | resultStr.append("/");
228 | resultStr.append(formatter.format(duration));
229 | return resultStr.toString();
230 | }
231 |
232 | public static String getVideoTimeFormatString(int time) {
233 | SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
234 | StringBuffer resultStr = new StringBuffer();
235 | resultStr.append(formatter.format(time));
236 | return resultStr.toString();
237 | }
238 |
239 | /**
240 | * 格式化时间
241 | * @param time 单位为毫秒级
242 | * @return
243 | */
244 | public static String formatToDoveBoxDate (Context context, String time)
245 | {
246 | if (context == null) return "";
247 | final Date currentData = new Date();
248 | final Date targetData = new Date(time);
249 | int intervalSeconds = (int) ((currentData.getTime() - targetData.getTime()) / 1000);
250 | int intervalMin = intervalSeconds / 60;
251 | if(intervalSeconds < 0 || intervalMin == 0) {
252 | return context.getString(R.string.just_now);
253 | }
254 | StringBuilder sb = new StringBuilder();
255 | if(intervalMin < 60 && intervalMin > 0) {
256 | sb.append(intervalMin).append(context.getString(R.string.minute_before));
257 | return sb.toString();
258 | }
259 | int intervalHour = intervalMin / 60;
260 | if(intervalHour < 24) {
261 | sb.append(intervalHour).append(context.getString(R.string.hour_before));
262 | return sb.toString();
263 | }
264 | int currentPassMin = currentData.getHours() * 60 + currentData.getMinutes();
265 | int targetPassMin = targetData.getHours() * 60 + targetData.getMinutes();
266 | int intervalDay = (intervalMin - ( targetPassMin - currentPassMin)) / (24 * 60);
267 | if(intervalDay < 3) {
268 | sb.append(intervalDay).append(context.getString(R.string.day_before));
269 | return sb.toString();
270 | }
271 | return mSimpleDateFormat2.format(targetData);
272 | }
273 |
274 | public static String getTakephotoFileName() {
275 | String randomUUID = UUID.randomUUID().toString();
276 | return randomUUID + ".jpg";
277 | }
278 |
279 | /**
280 | * 获取屏幕高度的方法
281 | *
282 | * @param context
283 | * @return 返回屏幕宽高
284 | */
285 | public static int[] getScreenHeightAndWidth(Context context){
286 | int[] returnIntArray = new int[2];
287 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
288 | returnIntArray[0] = dm.widthPixels;
289 | returnIntArray[1] = dm.heightPixels;
290 | return returnIntArray;
291 | }
292 |
293 | /**
294 | * 限制图片不要超过1M内存
295 | *
296 | * @param path
297 | * @return 返回小于1M的bitmap
298 | */
299 | public static Bitmap create1MBitmap(String path) {
300 | Options opts = new Options();
301 | opts.inJustDecodeBounds = true;
302 | BitmapFactory.decodeFile(path, opts);
303 | float m = 1024 * 1024;
304 | opts.inSampleSize = (int) Math.ceil(Math.sqrt(opts.outWidth * opts.outHeight * 4 / m) );
305 | opts.inJustDecodeBounds = false;
306 | Bitmap bitmap = null;
307 | try {
308 | bitmap = BitmapFactory.decodeFile(path, opts);
309 | } catch (OutOfMemoryError er) {
310 | bitmap = null;
311 | er.printStackTrace();
312 | } catch (Exception e) {
313 | bitmap = null;
314 | e.printStackTrace();
315 | }
316 | return bitmap;
317 |
318 | }
319 |
320 | public static Bitmap create1MBitmap(Bitmap bitmap) {
321 | float m = 1024 * 1024;
322 | int time = (int) Math.ceil(Math.sqrt(bitmap.getWidth() * bitmap.getHeight() * 4 / m) );
323 | Bitmap bitMap = null;
324 | try {
325 | bitMap = Bitmap.createBitmap(bitmap.getWidth() / time, bitmap.getHeight() / time, Config.ARGB_8888);
326 | } catch (OutOfMemoryError er) {
327 | bitmap = null;
328 | er.printStackTrace();
329 | } catch (Exception e) {
330 | bitmap = null;
331 | e.printStackTrace();
332 | }
333 | return bitMap;
334 | }
335 |
336 | /**
337 | * 取小图片
338 | *
339 | * @param path
340 | * @return
341 | */
342 | public static Bitmap createSmallBitmap(String path) {
343 | Options opts = new Options();
344 | opts.inJustDecodeBounds = true;
345 | BitmapFactory.decodeFile(path, opts);
346 | float m = 100 * 100;
347 | opts.inSampleSize = (int) Math.ceil(Math.sqrt(opts.outWidth * opts.outHeight * 4 / m) );
348 | opts.inJustDecodeBounds = false;
349 | Bitmap bitmap = null;
350 | try {
351 | bitmap = BitmapFactory.decodeFile(path, opts);
352 | } catch (OutOfMemoryError er) {
353 | bitmap = null;
354 | er.printStackTrace();
355 | } catch (Exception e) {
356 | bitmap = null;
357 | e.printStackTrace();
358 | }
359 | return bitmap;
360 | }
361 |
362 | /**
363 | * 创建小图
364 | *
365 | * @param path
366 | * @return
367 | */
368 | public static String createSmallImage(String path, String savePath) {
369 | Options opts = new Options();
370 | opts.inJustDecodeBounds = true;
371 | BitmapFactory.decodeFile(path, opts);
372 | if (opts.outWidth > 200 && opts.outHeight > 200) {
373 | opts.inSampleSize = Math.min(opts.outWidth / 200, opts.outHeight / 200);
374 | }
375 | opts.inJustDecodeBounds = false;
376 | Bitmap bitmap = null;
377 | try {
378 | bitmap = BitmapFactory.decodeFile(path, opts);
379 | } catch (OutOfMemoryError er) {
380 | bitmap = null;
381 | er.printStackTrace();
382 | } catch (Exception e) {
383 | bitmap = null;
384 | e.printStackTrace();
385 | }
386 |
387 | StringBuilder sb = new StringBuilder();
388 | sb.append(savePath);
389 | sb.append(System.currentTimeMillis());
390 | sb.append("temp.jpg");
391 | File file = new File(sb.toString());
392 | if (file.exists()) {
393 | file.delete();
394 | }
395 |
396 | BufferedOutputStream bos = null;
397 | try {
398 | bos = new BufferedOutputStream(new FileOutputStream(file));
399 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
400 | } catch(OutOfMemoryError e) {
401 | Log.e(Utils.class.getSimpleName(), e.toString());
402 | } catch (Exception e) {
403 | Log.e(Utils.class.getSimpleName(), e.toString());
404 | return "";
405 | } finally {
406 | if (bos != null) {
407 | try {
408 | bos.flush();
409 | bos.close();
410 | } catch (IOException e1) {
411 | e1.printStackTrace();
412 | return "";
413 | }
414 | }
415 | }
416 | return sb.toString();
417 | }
418 |
419 | /**
420 | * 创建一个新的文件(降低大于50Kb的图片的质量)用于网络传输
421 | *
422 | * @param savePath
423 | * @param bitmap
424 | * @return 返回新的图片或者为空。为空时表示没有生成新图片
425 | */
426 | public static String create50KBFile(String savePath, Bitmap bitmap, boolean isMake) {
427 | // int width = bitmap.getWidth();
428 | // int height = bitmap.getHeight();
429 | // if (!isMake && width * height < 1024 * 50) return "";
430 |
431 | StringBuilder sb = new StringBuilder();
432 | sb.append(savePath);
433 | sb.append(System.currentTimeMillis());
434 | sb.append("temp.jpg");
435 | File file = new File(sb.toString());
436 | if (file.exists()) {
437 | file.delete();
438 | }
439 |
440 | BufferedOutputStream bos = null;
441 | try {
442 | bos = new BufferedOutputStream(new FileOutputStream(file));
443 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
444 | } catch(OutOfMemoryError e) {
445 | Log.e(Utils.class.getSimpleName(), e.toString());
446 | } catch (Exception e) {
447 | Log.e(Utils.class.getSimpleName(), e.toString());
448 | return "";
449 | } finally {
450 | if (bos != null) {
451 | try {
452 | bos.flush();
453 | bos.close();
454 | } catch (IOException e1) {
455 | e1.printStackTrace();
456 | return "";
457 | }
458 | }
459 | }
460 | return sb.toString();
461 | }
462 |
463 | /**
464 | * 创建一个指定大小的正方形图片
465 | * @param path
466 | * @param width
467 | * @return
468 | */
469 | public static Bitmap createBitmap(String path, int width, float orientationDegree) {
470 | Bitmap bitmap = null;
471 | Options opts = new Options();
472 | opts.inJustDecodeBounds = true;
473 | BitmapFactory.decodeFile(path, opts);
474 | if (opts.outWidth > width && opts.outHeight > width) {
475 | opts.inSampleSize = Math.min(opts.outWidth / width, opts.outHeight / width);
476 | }
477 | opts.inJustDecodeBounds = false;
478 | try {
479 | bitmap = BitmapFactory.decodeFile(path, opts);
480 | int height = opts.outHeight;
481 | if (opts.outWidth < width) width = opts.outWidth;
482 | if (height > width) height = width;
483 | if(orientationDegree != 0) {
484 | Matrix m = new Matrix();
485 | m.setRotate(orientationDegree, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
486 | bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, true);
487 | } else {
488 | bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
489 | }
490 | } catch (OutOfMemoryError er) {
491 | bitmap = null;
492 | er.printStackTrace();
493 | } catch (Exception e) {
494 | bitmap = null;
495 | e.printStackTrace();
496 | }
497 | return bitmap;
498 | }
499 |
500 | /**
501 | * 获取自定义拍摄视频存储路径,缩略图问题待完善
502 | *
503 | * @throws IOException
504 | */
505 | public static File getOutputMediaFile(Context context, int type, String pathDir) throws IOException {
506 | String state = Environment.getExternalStorageState();
507 | if (!state.equals(Environment.MEDIA_MOUNTED)) {
508 | throw new IOException(context.getString(R.string.no_sdcard_string));
509 | } else {
510 | if (SystemSupport.readSDCard() < 3096) {
511 | throw new IOException(context.getString(R.string.no_space_string));
512 | }
513 | ;
514 | }
515 | File mediaStorageDir = new File(pathDir);
516 | if (!mediaStorageDir.exists()) {
517 | if (!mediaStorageDir.mkdirs()) {
518 | return null;
519 | }
520 | }
521 | // 创建媒体文件名
522 | String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
523 | File mediaFile;
524 | if (type == MEDIA_TYPE_VIDEO_THUMBNAIL) {
525 | mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp
526 | + ".jpg");
527 | } else if (type == MEDIA_TYPE_VIDEO) {
528 | mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp
529 | + ".mp4");
530 | } else if (type == MEDIA_TYPE_ZIP)
531 | {
532 | mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp
533 | + ".zip");
534 | }else {
535 |
536 | return null;
537 | }
538 | return mediaFile;
539 | }
540 |
541 | /**
542 | * 复制文件
543 | *
544 | * @param oldPath
545 | * @param newPath
546 | * @throws IOException
547 | */
548 | public static void onCopyPic(String oldPath, String newPath) throws IOException {
549 | File from = new File(oldPath);
550 | if (!from.exists() || !from.isFile() || !from.canRead()) {
551 | return;
552 | }
553 | File to = new File(newPath);
554 | if (!to.getParentFile().exists()) {
555 | to.getParentFile().mkdirs();
556 | }
557 | if (to.exists()) {
558 | to.delete();
559 | }
560 |
561 | FileInputStream fis = null;
562 | FileOutputStream fos = null;
563 | FileChannel input = null;
564 | FileChannel output = null;
565 | try {
566 | fis = new FileInputStream(from);
567 | fos = new FileOutputStream(to);
568 | input = fis.getChannel();
569 | output = fos.getChannel();
570 | long size = input.size();
571 | long pos = 0;
572 | long count = 0;
573 | while (pos < size) {
574 | count = size - pos > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : size - pos;
575 | pos += output.transferFrom(input, pos, count);
576 | }
577 | } finally {
578 | closeQuietly(output);
579 | closeQuietly(fos);
580 | closeQuietly(input);
581 | closeQuietly(fis);
582 | }
583 |
584 | if (from.length() != to.length()) {
585 | throw new IOException("Failed to copy full contents from '" +
586 | from + "' to '" + to + "'");
587 | }
588 | to.setLastModified(from.lastModified());
589 | }
590 |
591 | public static String getCameraPath() {
592 | String fileDir;
593 | if (new File("sdcard/Camera").exists()) {
594 | fileDir = "sdcard/Camera/";
595 | } else if (new File("sdcard/DCIM/Camera").exists()) {
596 | fileDir = "sdcard/DCIM/Camera/";
597 | } else {
598 | fileDir = "sdcard/DCIM/";
599 | }
600 | return fileDir;
601 | }
602 |
603 | private static void closeQuietly(OutputStream output) {
604 | closeQuietly((Closeable)output);
605 | }
606 |
607 | private static void closeQuietly(Closeable closeable) {
608 | try {
609 | if (closeable != null) {
610 | closeable.close();
611 | }
612 | } catch (IOException ioe) {
613 | // ignore
614 | }
615 | }
616 |
617 | /**
618 | * 取小图片
619 | *
620 | * @param path
621 | * @return
622 | */
623 | public static Bitmap createChatBitmap(String path) {
624 | Options opts = new Options();
625 | opts.inJustDecodeBounds = true;
626 | BitmapFactory.decodeFile(path, opts);
627 | float m = 150 * 150;
628 | opts.inSampleSize = (int) Math.ceil(Math.sqrt(opts.outWidth * opts.outHeight * 4 / m) );
629 | opts.inJustDecodeBounds = false;
630 | Bitmap bitmap = null;
631 | try {
632 | bitmap = BitmapFactory.decodeFile(path, opts);
633 | } catch (OutOfMemoryError er) {
634 | bitmap = null;
635 | er.printStackTrace();
636 | } catch (Exception e) {
637 | bitmap = null;
638 | e.printStackTrace();
639 | }
640 | return bitmap;
641 | }
642 |
643 | public final static Object objectCopy(Object oldObj) {
644 | Object newObj = null;
645 | try {
646 | ByteArrayOutputStream bo = new ByteArrayOutputStream();
647 | ObjectOutputStream oo = new ObjectOutputStream(bo);
648 | oo.writeObject(oldObj);//源对象
649 | ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
650 | ObjectInputStream oi= new ObjectInputStream(bi);
651 | newObj = oi.readObject();//目标对象
652 | } catch (IOException e) {
653 | e.printStackTrace();
654 | }catch (ClassNotFoundException e) {
655 | e.printStackTrace();
656 | }
657 | return newObj;
658 | }
659 | }
660 |
--------------------------------------------------------------------------------