diff --git a/app/build.gradle b/app/build.gradle index 9ccd36c..894c9e9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' apply plugin: 'channel' -channel{ +channel { //指定渠道文件 channelFile = file("channel.txt") //多渠道包的输出目录,默认为new File(project.buildDir,"channel") - baseOutputDir = new File(project.buildDir,"channel") + baseOutputDir = new File(project.buildDir, "channel") //多渠道包的命名规则,默认为:${appName}-${versionName}-${versionCode}-${flavorName}-${buildType} - apkNameFormat ='${appName}-${versionName}-${flavorName}-${buildType}' + apkNameFormat = '${appName}-${versionName}-${flavorName}-${buildType}' //快速模式:生成渠道包时不进行校验(速度可以提升10倍以上) isFastMode = true } @@ -50,6 +50,25 @@ android { } } + packagingOptions { + exclude 'lib/mips64/*.so' + exclude 'lib/mips/*.so' + exclude 'META-INF/proguard/androidx-annotations.pro' + exclude 'META-INF/androidx.localbroadcastmanager_localbroadcastmanager.version' + exclude 'META-INF/androidx.customview_customview.version' + exclude 'META-INF/androidx.legacy_legacy-support-core-ui.version' + exclude 'META-INF/androidx.*' + + exclude 'META-INF/DEPENDENCIES' + exclude 'META-INF/NOTICE' + exclude 'META-INF/LICENSE' + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/NOTICE.txt' + + exclude 'META-INF/maven/com.belerweb/pinyin4j/pom.xml' + exclude 'META-INF/maven/com.belerweb/pinyin4j/pom.properties' + } + File customerproguardFile = file('src/proguard.cfg') buildTypes { release { @@ -101,14 +120,16 @@ dependencies { /*RecycleView的间隔线*/ implementation 'com.yqritc:recyclerview-flexibledivider:1.2.9' /*解析Json*/ - implementation 'com.google.code.gson:gson:2.7' + implementation 'com.google.code.gson:gson:2.8.5' /*网络相关*/ - implementation 'com.squareup.okhttp3:okhttp:3.3.1' + implementation 'com.squareup.okhttp3:okhttp:3.11.0' implementation 'com.squareup.retrofit2:retrofit:2.1.0' implementation 'com.squareup.retrofit2:converter-gson:2.1.0' /*图片加载Glide*/ implementation 'com.github.bumptech.glide:glide:4.8.0' implementation 'jp.wasabeef:glide-transformations:2.0.2' + /*数据存储*/ + implementation 'com.tencent:mmkv-static:1.2.2' /*日志*/ implementation 'com.github.zhaokaiqiang.klog:library:1.6.0' /*注解*/ @@ -138,6 +159,7 @@ dependencies { /* 模糊 */ implementation 'jp.wasabeef:blurry:2.1.1' /*网络监测*/ + implementation 'com.android.support.constraint:constraint-layout:2.0.2' debugImplementation 'com.readystatesoftware.chuck:library:1.1.0' releaseImplementation 'com.readystatesoftware.chuck:library-no-op:1.1.0' /* 表格 */ @@ -162,6 +184,8 @@ dependencies { implementation 'com.github.chrisbanes:PhotoView:2.0.0' /* ----------自己------------ */ + /*二维码扫描*/ + implementation 'com.github.maning0303:MNZXingCode:V2.1.4' /*翻滚广告条TextView*/ implementation 'com.github.maning0303:SwitcherView:v1.0.4' /* 提示框 */ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2f474f6..d25ae7f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,57 +1,40 @@ + xmlns:tools="http://schemas.android.com/tools" + package="com.maning.gankmm"> - + - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:protectionLevel="signature" /> + + + + + + + + + + + + + + + + + + + + + + + + + + tools:replace="icon,label,theme,allowBackup"> + + - - - + android:resource="@xml/file_paths" /> + - - - - + + + + - - - + - + - + - - - + - + - + - - + + - - + + - + - - - + - + - - + + - - + - - + + - - - + - - - - - + android:exported="false" /> + - + - + - + - + - + - + - - - + + android:value="developer-default" /> - - + android:value="9154ee1b9e0fac4b4d967222" /> - + - + + android:screenOrientation="portrait" /> + android:screenOrientation="portrait" /> + android:screenOrientation="portrait" /> + android:screenOrientation="portrait" /> + android:screenOrientation="portrait" /> + android:screenOrientation="portrait" /> + android:screenOrientation="portrait" /> - - + android:windowSoftInputMode="adjustPan" /> - + android:value="48cc89a5931e80321bced46714a03563" /> + + + android:screenOrientation="portrait" /> + android:screenOrientation="portrait" /> + android:screenOrientation="portrait" /> - - - - - - - - - - - - - - - - - + android:screenOrientation="portrait" /> + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:theme="@style/ImageBrowserTheme" /> + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/maning/gankmm/app/MyApplication.java b/app/src/main/java/com/maning/gankmm/app/MyApplication.java index aa58e9e..409710c 100644 --- a/app/src/main/java/com/maning/gankmm/app/MyApplication.java +++ b/app/src/main/java/com/maning/gankmm/app/MyApplication.java @@ -12,12 +12,12 @@ import com.leon.channel.helper.ChannelReaderUtil; import com.maning.gankmm.BuildConfig; -import com.maning.gankmm.utils.ACache; -import com.maning.gankmm.utils.MyToast; +import com.maning.gankmm.utils.CacheDiskUtils; import com.maning.gankmm.utils.NetUtils; import com.maning.librarycrashmonitor.MCrashMonitor; import com.readystatesoftware.chuck.ChuckInterceptor; import com.socks.library.KLog; +import com.tencent.mmkv.MMKV; import com.umeng.analytics.MobclickAgent; import com.umeng.commonsdk.UMConfigure; @@ -42,7 +42,6 @@ public class MyApplication extends Application { private static MyApplication application; private static Handler mHandler; - private static ACache aCache; @Override protected void attachBaseContext(Context base) { @@ -118,15 +117,10 @@ private void initJpush() { private void initBase() { application = this; mHandler = new Handler(); - //初始化ACache类 - aCache = ACache.get(this); + CacheDiskUtils.init(this); + MMKV.initialize(this); } - public static ACache getACache() { - return aCache; - } - - private void initCrash() { /** * 初始化日志系统 diff --git a/app/src/main/java/com/maning/gankmm/http/mob/MobApi.java b/app/src/main/java/com/maning/gankmm/http/mob/MobApi.java index db69bcc..bca121b 100644 --- a/app/src/main/java/com/maning/gankmm/http/mob/MobApi.java +++ b/app/src/main/java/com/maning/gankmm/http/mob/MobApi.java @@ -70,8 +70,6 @@ public void onResponse(Call call, Response response) { if (response.isSuccessful()) { CitysEntity citysEntity = response.body(); if (citysEntity != null) { - //保存 - UserUtils.saveCitysCache(citysEntity); if (citysEntity.getMsg().equals("success")) { KLog.i("getCitys---success:" + citysEntity.toString()); myCallBack.onSuccessList(what, citysEntity.getResult()); diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/CitysActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/CitysActivity.java index 48610f5..13a9225 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/CitysActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/CitysActivity.java @@ -14,7 +14,6 @@ import com.maning.gankmm.skin.SkinManager; import com.maning.gankmm.ui.adapter.RecycleCitysAdapter; import com.maning.gankmm.ui.base.BaseActivity; -import com.maning.gankmm.utils.UserUtils; import java.util.ArrayList; import java.util.HashMap; @@ -24,6 +23,7 @@ import butterknife.Bind; import butterknife.ButterKnife; +@Deprecated public class CitysActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -58,7 +58,7 @@ protected void onCreate(Bundle savedInstanceState) { private void initAdapter() { //获取数据 - CitysEntity citysCache = UserUtils.getCitysCache(); + CitysEntity citysCache = null; if (citysCache != null) { List cityList = citysCache.getResult(); for (int i = 0; i < cityList.size(); i++) { @@ -124,12 +124,7 @@ private void initViews() { private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(toolbar, "城市选择", R.drawable.gank_ic_back_white); - } else { - initToolBar(toolbar, "城市选择", R.drawable.gank_ic_back_night); - } + initBackToolBar(toolbar, "城市选择"); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/CodesActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/CodesActivity.java index 04b7a1b..91cc478 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/CodesActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/CodesActivity.java @@ -46,7 +46,6 @@ * 泡在网上的日子的数据的抓取 * 网站异常,废弃 */ -@Deprecated public class CodesActivity extends BaseActivity implements OnRefreshListener, OnLoadMoreListener, ICodesView { @Bind(R.id.toolbar) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/login/EditUserInfoActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/login/EditUserInfoActivity.java index 8e0612d..b75925b 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/login/EditUserInfoActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/login/EditUserInfoActivity.java @@ -19,14 +19,13 @@ import com.luck.picture.lib.entity.LocalMedia; import com.maning.gankmm.R; import com.maning.gankmm.bean.mob.MobUserInfo; -import com.maning.gankmm.http.mob.MobApi; import com.maning.gankmm.http.callback.MyCallBack; +import com.maning.gankmm.http.mob.MobApi; import com.maning.gankmm.skin.SkinManager; import com.maning.gankmm.ui.base.BaseActivity; import com.maning.gankmm.utils.AppDateMgr; import com.maning.gankmm.utils.DialogUtils; import com.maning.gankmm.utils.MySnackbar; -import com.maning.gankmm.utils.UserUtils; import com.socks.library.KLog; import java.text.ParseException; @@ -43,6 +42,7 @@ /** * 编辑用户信息页面 */ +@Deprecated public class EditUserInfoActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -78,7 +78,7 @@ protected void onCreate(Bundle savedInstanceState) { private void initDatas() { //获取信息 - mUserCache = UserUtils.getUserCache(); +// mUserCache = UserUtils.getUserCache(); //设置头像 RequestOptions options = new RequestOptions(); options.placeholder(R.drawable.icon_default_avatar); @@ -267,8 +267,6 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { public void onSuccess(int what, Object result) { dissmissProgressDialog(); if (what == 0x001) { - //保存用户信息 - UserUtils.saveUserCache(mUserCache); //保存成功 MySnackbar.makeSnackBarGreen(mToolbar, "数据更新成功"); @@ -285,12 +283,12 @@ public void onSuccess(int what, Object result) { String signature = values[2]; //本地数据更新 - MobUserInfo userCache = UserUtils.getUserCache(); - userCache.setSex(sex); - userCache.setBirth(birth); - userCache.setSignature(signature); - //保存用户信息 - UserUtils.saveUserCache(userCache); +// MobUserInfo userCache = UserUtils.getUserCache(); +// userCache.setSex(sex); +// userCache.setBirth(birth); +// userCache.setSignature(signature); +// //保存用户信息 +// UserUtils.saveUserCache(userCache); //刷新界面 initDatas(); } @@ -331,39 +329,39 @@ private void queryUserInfo() { @Override public void onBackPressed() { //对比数据 - MobUserInfo userCacheBefore = UserUtils.getUserCache(); - - String avatarLocal = userCacheBefore.getAvatarLocal(); - String sex = userCacheBefore.getSex(); - String birth = userCacheBefore.getBirth(); - String signature = userCacheBefore.getSignature(); - - String avatarLocal_new = mUserCache.getAvatarLocal(); - String sex_new = mUserCache.getSex(); - String birth_new = mUserCache.getBirth(); - String signature_new = mUserCache.getSignature(); - - if ( - (TextUtils.isEmpty(avatarLocal) ? "" : avatarLocal).equals((TextUtils.isEmpty(avatarLocal_new) ? "" : avatarLocal_new)) && - (TextUtils.isEmpty(sex) ? "" : sex).equals((TextUtils.isEmpty(sex_new) ? "" : sex_new)) && - (TextUtils.isEmpty(birth) ? "" : birth).equals((TextUtils.isEmpty(birth_new) ? "" : birth_new)) && - (TextUtils.isEmpty(signature) ? "" : signature).equals((TextUtils.isEmpty(signature_new) ? "" : signature_new)) - ) { - //关闭页面 - EditUserInfoActivity.this.finish(); - } else { - DialogUtils.showMyDialog(mContext, "提示", "您有数据发生了修改,需要保存吗?", "不修改了,关闭页面", "去保存", new DialogUtils.OnDialogClickListener() { - @Override - public void onConfirm() { - //关闭页面 - EditUserInfoActivity.this.finish(); - } - - @Override - public void onCancel() { - - } - }); - } +// MobUserInfo userCacheBefore = UserUtils.getUserCache(); + +// String avatarLocal = userCacheBefore.getAvatarLocal(); +// String sex = userCacheBefore.getSex(); +// String birth = userCacheBefore.getBirth(); +// String signature = userCacheBefore.getSignature(); +// +// String avatarLocal_new = mUserCache.getAvatarLocal(); +// String sex_new = mUserCache.getSex(); +// String birth_new = mUserCache.getBirth(); +// String signature_new = mUserCache.getSignature(); +// +// if ( +// (TextUtils.isEmpty(avatarLocal) ? "" : avatarLocal).equals((TextUtils.isEmpty(avatarLocal_new) ? "" : avatarLocal_new)) && +// (TextUtils.isEmpty(sex) ? "" : sex).equals((TextUtils.isEmpty(sex_new) ? "" : sex_new)) && +// (TextUtils.isEmpty(birth) ? "" : birth).equals((TextUtils.isEmpty(birth_new) ? "" : birth_new)) && +// (TextUtils.isEmpty(signature) ? "" : signature).equals((TextUtils.isEmpty(signature_new) ? "" : signature_new)) +// ) { +// //关闭页面 +// EditUserInfoActivity.this.finish(); +// } else { +// DialogUtils.showMyDialog(mContext, "提示", "您有数据发生了修改,需要保存吗?", "不修改了,关闭页面", "去保存", new DialogUtils.OnDialogClickListener() { +// @Override +// public void onConfirm() { +// //关闭页面 +// EditUserInfoActivity.this.finish(); +// } +// +// @Override +// public void onCancel() { +// +// } +// }); +// } } } diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/login/LoginActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/login/LoginActivity.java index ba45a08..fdb6a3e 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/login/LoginActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/login/LoginActivity.java @@ -15,7 +15,6 @@ import com.maning.gankmm.ui.base.BaseActivity; import com.maning.gankmm.utils.KeyboardUtils; import com.maning.gankmm.utils.MySnackbar; -import com.maning.gankmm.utils.UserUtils; import java.util.List; @@ -27,6 +26,7 @@ /** * 登录页面 */ +@Deprecated public class LoginActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -97,7 +97,7 @@ public void onSuccess(int what, Object result) { userInfo.setUserPsd(userPsd); //保存用户信息 - UserUtils.saveUserCache(userInfo); +// UserUtils.saveUserCache(userInfo); //关闭当前页面。 closeAcitivity(); diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/login/UserInfoActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/login/UserInfoActivity.java index 1ef8cd5..c91c5d2 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/login/UserInfoActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/login/UserInfoActivity.java @@ -22,6 +22,7 @@ import butterknife.OnClick; import de.hdodenhof.circleimageview.CircleImageView; +@Deprecated public class UserInfoActivity extends BaseActivity { @Bind(R.id.avatar) @@ -108,14 +109,14 @@ protected void onResume() { } private void refreshUserInfo() { - //刷新数据 - mUserCache = UserUtils.getUserCache(); - //设置头像 - RequestOptions options = new RequestOptions(); - options.placeholder(R.drawable.icon_default_avatar); - options.error(R.drawable.icon_default_avatar); - Glide.with(mContext).load(mUserCache.getAvatarLocal()).apply(options).into(mAvatar); - //设置用户名 - mTvUserName.setText(mUserCache.getUserName()); +// //刷新数据 +// mUserCache = UserUtils.getUserCache(); +// //设置头像 +// RequestOptions options = new RequestOptions(); +// options.placeholder(R.drawable.icon_default_avatar); +// options.error(R.drawable.icon_default_avatar); +// Glide.with(mContext).load(mUserCache.getAvatarLocal()).apply(options).into(mAvatar); +// //设置用户名 +// mTvUserName.setText(mUserCache.getUserName()); } } diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/BankCardActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/BankCardActivity.java index a7d933a..561e2b2 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/BankCardActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/BankCardActivity.java @@ -30,6 +30,7 @@ /** * 银行卡查询 */ +@Deprecated public class BankCardActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -59,12 +60,7 @@ private void initRecyclerView() { } private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(toolbar, "银行卡查询", R.drawable.gank_ic_back_white); - } else { - initToolBar(toolbar, "银行卡查询", R.drawable.gank_ic_back_night); - } + initBackToolBar(toolbar, "银行卡查询"); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarDetailActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarDetailActivity.java index e1b8c95..3c98396 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarDetailActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarDetailActivity.java @@ -26,6 +26,7 @@ /** * 车型详细配置 */ +@Deprecated public class CarDetailActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -202,12 +203,7 @@ private void initRecyclerView() { } private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(mToolbar, mMobCarItemEntity.getSeriesName(), R.drawable.gank_ic_back_white); - } else { - initToolBar(mToolbar, mMobCarItemEntity.getSeriesName(), R.drawable.gank_ic_back_night); - } + initBackToolBar(mToolbar, mMobCarItemEntity.getSeriesName()); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarItemsActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarItemsActivity.java index e9ea660..442b2fc 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarItemsActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarItemsActivity.java @@ -27,6 +27,7 @@ import butterknife.Bind; import butterknife.ButterKnife; +@Deprecated public class CarItemsActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -102,12 +103,7 @@ private void initRecyclerView() { } private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(mToolbar, mSonBean.getType(), R.drawable.gank_ic_back_white); - } else { - initToolBar(mToolbar, mSonBean.getType(), R.drawable.gank_ic_back_night); - } + initBackToolBar(mToolbar, mSonBean.getType()); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarListActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarListActivity.java index b1a39f2..9c79443 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarListActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CarListActivity.java @@ -36,6 +36,7 @@ import butterknife.ButterKnife; import butterknife.OnClick; +@Deprecated public class CarListActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -196,12 +197,7 @@ private void initRecyclerView() { } private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(mToolbar, "汽车品牌", R.drawable.gank_ic_back_white); - } else { - initToolBar(mToolbar, "汽车品牌", R.drawable.gank_ic_back_night); - } + initBackToolBar(mToolbar, "汽车品牌"); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookDetailsActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookDetailsActivity.java index 3ec611e..882a6bb 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookDetailsActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookDetailsActivity.java @@ -19,6 +19,7 @@ /** * 做菜详情 */ +@Deprecated public class CookDetailsActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -62,12 +63,7 @@ private void initIntent() { } private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(mToolbar, mData.getRecipe().getTitle(), R.drawable.gank_ic_back_white); - } else { - initToolBar(mToolbar, mData.getRecipe().getTitle(), R.drawable.gank_ic_back_night); - } + initBackToolBar(mToolbar, mData.getRecipe().getTitle()); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookListActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookListActivity.java index 389239a..2cd229f 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookListActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookListActivity.java @@ -36,6 +36,7 @@ /** * 菜谱列表页面 */ +@Deprecated public class CookListActivity extends BaseActivity implements OnRefreshListener, OnLoadMoreListener { @Bind(R.id.toolbar) @@ -101,12 +102,7 @@ private void initViews() { } private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(mToolbar, mMobCookCategoryEntity.getCategoryInfo().getName(), R.drawable.gank_ic_back_white); - } else { - initToolBar(mToolbar, mMobCookCategoryEntity.getCategoryInfo().getName(), R.drawable.gank_ic_back_night); - } + initBackToolBar(mToolbar, mMobCookCategoryEntity.getCategoryInfo().getName()); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookMenuActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookMenuActivity.java index 9bed8fc..4a6513b 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookMenuActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/CookMenuActivity.java @@ -27,6 +27,7 @@ /** * 菜谱首页 */ +@Deprecated public class CookMenuActivity extends BaseActivity { @Bind(R.id.toolbar) @@ -55,12 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { } private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(mToolbar, "我的厨房", R.drawable.gank_ic_back_white); - } else { - initToolBar(mToolbar, "我的厨房", R.drawable.gank_ic_back_night); - } + initBackToolBar(mToolbar, "我的厨房"); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/DictionaryActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/DictionaryActivity.java index 9d8f1be..cb5786f 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/DictionaryActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/DictionaryActivity.java @@ -58,12 +58,7 @@ private void initRecyclerView() { } private void initMyToolBar() { - int currentSkinType = SkinManager.getCurrentSkinType(this); - if (SkinManager.THEME_DAY == currentSkinType) { - initToolBar(toolbar, "新华字典查询", R.drawable.gank_ic_back_white); - } else { - initToolBar(toolbar, "新华字典查询", R.drawable.gank_ic_back_night); - } + initBackToolBar(toolbar, "新华字典查询"); } @Override diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/FlightActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/FlightActivity.java index b71ce95..716606c 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/FlightActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/FlightActivity.java @@ -34,6 +34,7 @@ /** * 航班 */ +@Deprecated public class FlightActivity extends BaseActivity { @Bind(R.id.ll_query) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/FlightListActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/FlightListActivity.java index 42f62bb..d7c752b 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/FlightListActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/FlightListActivity.java @@ -28,6 +28,7 @@ /** * 航班列表查询 */ +@Deprecated public class FlightListActivity extends BaseActivity { @Bind(R.id.toolbar) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/IDCardQueryActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/IDCardQueryActivity.java index d6f64a8..f8772b1 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/IDCardQueryActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/IDCardQueryActivity.java @@ -30,6 +30,7 @@ /** * 身份证查询 */ +@Deprecated public class IDCardQueryActivity extends BaseActivity { @Bind(R.id.toolbar) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/LotteryCategoryActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/LotteryCategoryActivity.java index b6189a9..3f27576 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/LotteryCategoryActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/LotteryCategoryActivity.java @@ -27,6 +27,7 @@ /** * 彩票分类 */ +@Deprecated public class LotteryCategoryActivity extends BaseActivity { @Bind(R.id.toolbar) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/LotteryDetailActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/LotteryDetailActivity.java index 6022578..ac01d40 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/LotteryDetailActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/LotteryDetailActivity.java @@ -26,6 +26,7 @@ /** * 彩票详情 */ +@Deprecated public class LotteryDetailActivity extends BaseActivity { @Bind(R.id.toolbar) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/OilPriceActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/OilPriceActivity.java index 1d60ad3..e809d50 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/OilPriceActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/OilPriceActivity.java @@ -26,6 +26,7 @@ /** * 全国油价信息 */ +@Deprecated public class OilPriceActivity extends BaseActivity { private static final String TAG = "OilPriceActivity"; diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/PostCodeActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/PostCodeActivity.java index 50aaa5a..d8c2364 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/PostCodeActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/PostCodeActivity.java @@ -30,6 +30,7 @@ /** * 邮编查询 */ +@Deprecated public class PostCodeActivity extends BaseActivity { @Bind(R.id.toolbar) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/ScanResultActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/ScanResultActivity.java new file mode 100644 index 0000000..f24f5e1 --- /dev/null +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/ScanResultActivity.java @@ -0,0 +1,126 @@ +package com.maning.gankmm.ui.activity.tools; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.Button; +import android.widget.TextView; + +import com.maning.gankmm.R; +import com.maning.gankmm.skin.SkinManager; +import com.maning.gankmm.ui.adapter.RecycleScanHistoryAdapter; +import com.maning.gankmm.ui.base.BaseActivity; +import com.maning.gankmm.utils.CacheManager; +import com.maning.gankmm.utils.ClipUtils; +import com.maning.gankmm.utils.MMKVUtils; +import com.maning.gankmm.utils.MySnackbar; +import com.maning.gankmm.utils.ThreadPoolUtils; +import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.Bind; +import butterknife.ButterKnife; +import butterknife.OnClick; + +/** + * 扫码结果页面 + */ +public class ScanResultActivity extends BaseActivity { + + @Bind(R.id.toolbar) + Toolbar toolbar; + @Bind(R.id.recyclerView) + RecyclerView recyclerView; + @Bind(R.id.tv_show) + TextView tvShow; + private String content; + private List scanResult = new ArrayList<>(); + private RecycleScanHistoryAdapter recycleScanHistoryAdapter; + + public static void open(Context context, String content) { + Intent intent = new Intent(context, ScanResultActivity.class); + intent.putExtra("content", content); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_scan_result); + ButterKnife.bind(this); + initIntent(); + initBackToolBar(toolbar, "扫码结果"); + initRecyclerView(); + initDatas(); + } + + private void initDatas() { + tvShow.setText(content); + + //获取扫码历史 + ThreadPoolUtils.execute(new Runnable() { + @Override + public void run() { + scanResult = CacheManager.getScanResult(); + runOnUiThread(new Runnable() { + @Override + public void run() { + recycleScanHistoryAdapter = new RecycleScanHistoryAdapter(mActivity, (ArrayList) scanResult); + recyclerView.setAdapter(recycleScanHistoryAdapter); + } + }); + } + }); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + this.finish(); + return true; + case R.id.item_delete: + //TODO:删除提示 + + + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_scan_history_toolbar, menu); + return true; + } + + private void initIntent() { + content = getIntent().getStringExtra("content"); + if (!TextUtils.isEmpty(content)) { + CacheManager.saveScanResult(content); + } + } + + private void initRecyclerView() { + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); + recyclerView.setLayoutManager(linearLayoutManager); + recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this).color(Color.LTGRAY).build()); + } + + @OnClick(R.id.btn_copy) + public void btn_copy() { + //复制到剪切板 + ClipUtils.copy(mActivity, tvShow.getText().toString()); + MySnackbar.makeSnackBarGreen(toolbar, "结果已经复制到剪切板"); + } +} diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/TrainActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/TrainActivity.java index 30a87b6..ed27384 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/TrainActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/TrainActivity.java @@ -34,6 +34,7 @@ /** * 火车 */ +@Deprecated public class TrainActivity extends BaseActivity { @Bind(R.id.ll_query) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/TrainListActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/TrainListActivity.java index c839e58..70631b4 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/TrainListActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/TrainListActivity.java @@ -33,6 +33,7 @@ /** * 火车列表查询 */ +@Deprecated public class TrainListActivity extends BaseActivity { @Bind(R.id.toolbar) diff --git a/app/src/main/java/com/maning/gankmm/ui/activity/tools/WXArticleActivity.java b/app/src/main/java/com/maning/gankmm/ui/activity/tools/WXArticleActivity.java index eec7952..1832db4 100644 --- a/app/src/main/java/com/maning/gankmm/ui/activity/tools/WXArticleActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/activity/tools/WXArticleActivity.java @@ -38,6 +38,7 @@ /** * 微信精选 */ +@Deprecated public class WXArticleActivity extends BaseActivity implements OnRefreshListener, OnLoadMoreListener { @Bind(R.id.toolbar) diff --git a/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleMoreAdapter.java b/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleMoreAdapter.java index 5f51c45..de31ad3 100644 --- a/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleMoreAdapter.java +++ b/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleMoreAdapter.java @@ -1,5 +1,6 @@ package com.maning.gankmm.ui.adapter; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.support.v7.widget.DefaultItemAnimator; @@ -21,6 +22,7 @@ import com.maning.gankmm.ui.activity.tools.HistoryTodayActivity; import com.maning.gankmm.ui.activity.tools.IDCardQueryActivity; import com.maning.gankmm.ui.activity.tools.IPQueryActivity; +import com.maning.gankmm.ui.activity.tools.ScanResultActivity; import com.maning.gankmm.ui.activity.tools.WorldPhoneCodeActivity; import com.maning.gankmm.ui.activity.tools.LotteryCategoryActivity; import com.maning.gankmm.ui.activity.tools.OilPriceActivity; @@ -30,6 +32,7 @@ import com.maning.gankmm.ui.activity.tools.WXArticleActivity; import com.maning.gankmm.utils.IntentUtils; import com.maning.gankmm.utils.MySnackbar; +import com.maning.gankmm.utils.ZxingScanUtils; import java.util.ArrayList; import java.util.List; @@ -74,6 +77,9 @@ public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int //便民服务 mDatasItem.add("垃圾分类"); mDatasItem.add("新华字典"); + mDatasItem.add("二维码生成"); + mDatasItem.add("扫一扫"); + mDatasItem.add("扫码记录"); // mDatasItem.add("邮编查询"); // mDatasItem.add("菜谱查询"); // mDatasItem.add("身份证查询"); @@ -111,6 +117,10 @@ public void onItemClick(View view, int position) { String title = mDatasTitle.get(position); if (title.equals("手机号码归属地")) { context.startActivity(new Intent(context, PhoneAddressActivity.class)); + } else if (title.equals("扫一扫")) { + ZxingScanUtils.open((Activity) context); + } else if (title.equals("扫码记录")) { + context.startActivity(new Intent(context, ScanResultActivity.class)); } else if (title.equals("邮编查询")) { context.startActivity(new Intent(context, PostCodeActivity.class)); } else if (title.equals("菜谱查询")) { @@ -123,7 +133,7 @@ public void onItemClick(View view, int position) { context.startActivity(new Intent(context, LotteryCategoryActivity.class)); } else if (title.equals("微信精选")) { context.startActivity(new Intent(context, WXArticleActivity.class)); - }else if (title.equals("周公解梦")) { + } else if (title.equals("周公解梦")) { IntentUtils.startToWebActivity(context, "工具", "周公解梦", "http://tools.2345.com/zhgjm.htm"); } else if (title.equals("婚姻匹配")) { IntentUtils.startToWebActivity(context, "工具", "婚姻匹配", "http://www.jjdzc.com/peidui/hehun.html"); @@ -139,7 +149,7 @@ public void onItemClick(View view, int position) { context.startActivity(new Intent(context, FlightActivity.class)); } else if (title.equals("足球五大联赛")) { MySnackbar.makeSnackBarGreen(myViewHolder.recyclerViewItem, "功能暂未开通,敬请期待"); - }else if (title.equals("垃圾分类")) { + } else if (title.equals("垃圾分类")) { context.startActivity(new Intent(context, RubbishActivity.class)); } else if (title.equals("历史上的今天")) { context.startActivity(new Intent(context, HistoryTodayActivity.class)); diff --git a/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleMoreItemAdapter.java b/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleMoreItemAdapter.java index dc82763..9ae6d56 100644 --- a/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleMoreItemAdapter.java +++ b/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleMoreItemAdapter.java @@ -39,6 +39,9 @@ public class RecycleMoreItemAdapter extends RecyclerView.Adapter m @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View inflate = layoutInflater.inflate(R.layout.item_health, parent, false); + View inflate = layoutInflater.inflate(R.layout.item_rubbish, parent, false); return new MyViewHolder(inflate); } diff --git a/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleScanHistoryAdapter.java b/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleScanHistoryAdapter.java new file mode 100644 index 0000000..e0cbc9d --- /dev/null +++ b/app/src/main/java/com/maning/gankmm/ui/adapter/RecycleScanHistoryAdapter.java @@ -0,0 +1,76 @@ +package com.maning.gankmm.ui.adapter; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.maning.gankmm.R; +import com.maning.gankmm.utils.ClipUtils; +import com.maning.gankmm.utils.MySnackbar; + +import java.util.ArrayList; + +import butterknife.Bind; +import butterknife.ButterKnife; + +/** + * 扫码历史 + */ +public class RecycleScanHistoryAdapter extends RecyclerView.Adapter { + + private Context context; + private ArrayList mDatas; + private LayoutInflater layoutInflater; + + public RecycleScanHistoryAdapter(Context context, ArrayList mDatas) { + this.context = context; + this.mDatas = mDatas; + layoutInflater = LayoutInflater.from(this.context); + } + + @Override + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View inflate = layoutInflater.inflate(R.layout.item_scan_history, parent, false); + return new MyViewHolder(inflate); + } + + @Override + public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) { + if (viewHolder instanceof MyViewHolder) { + final MyViewHolder myViewHolder = (MyViewHolder) viewHolder; + + final String result = mDatas.get(position); + myViewHolder.tv_title.setText(result); + myViewHolder.root_view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //复制到剪切板 + ClipUtils.copy(context, result); + MySnackbar.makeSnackBarGreen(myViewHolder.root_view, "结果已经复制到剪切板"); + } + }); + } + } + + @Override + public int getItemCount() { + return mDatas.size(); + } + + class MyViewHolder extends RecyclerView.ViewHolder { + + @Bind(R.id.tv_title) + TextView tv_title; + @Bind(R.id.root_view) + RelativeLayout root_view; + + public MyViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } +} diff --git a/app/src/main/java/com/maning/gankmm/ui/base/BaseActivity.java b/app/src/main/java/com/maning/gankmm/ui/base/BaseActivity.java index 55fcefd..48c6046 100644 --- a/app/src/main/java/com/maning/gankmm/ui/base/BaseActivity.java +++ b/app/src/main/java/com/maning/gankmm/ui/base/BaseActivity.java @@ -69,9 +69,20 @@ public void dissmissProgressDialog() { MProgressDialog.dismissProgress(); } + public void initBackToolBar(Toolbar toolbar, String title) { + int currentSkinType = SkinManager.getCurrentSkinType(this); + if (SkinManager.THEME_DAY == currentSkinType) { + initToolBar(toolbar, title, R.drawable.gank_ic_back_white); + } else { + initToolBar(toolbar, title, R.drawable.gank_ic_back_night); + } + } + public void initToolBar(Toolbar toolbar, String title, int icon) { toolbar.setTitle(title);// 标题的文字需在setSupportActionBar之前,不然会无效 - toolbar.setNavigationIcon(icon); + if(icon > 0){ + toolbar.setNavigationIcon(icon); + } setSupportActionBar(toolbar); int currentSkinType = SkinManager.getCurrentSkinType(this); if (SkinManager.THEME_DAY == currentSkinType) { diff --git a/app/src/main/java/com/maning/gankmm/utils/ACache.java b/app/src/main/java/com/maning/gankmm/utils/ACache.java deleted file mode 100755 index 3e65319..0000000 --- a/app/src/main/java/com/maning/gankmm/utils/ACache.java +++ /dev/null @@ -1,919 +0,0 @@ -/** - * Copyright (c) 2012-2013, Michael Yang 杨福海 (www.yangfuhai.com). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.maning.gankmm.utils; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.io.RandomAccessFile; -import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import org.json.JSONArray; -import org.json.JSONObject; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.PixelFormat; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; - -/** - * @author Michael Yang(www.yangfuhai.com) update at 2013.08.07 - */ -public class ACache { - public static final int TIME_HOUR = 60 * 60; - public static final int TIME_DAY = TIME_HOUR * 24; - private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb - private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量 - private static Map mInstanceMap = new HashMap(); - private ACacheManager mCache; - - public static ACache get(Context ctx) { - return get(ctx, "ACache"); - } - - public static ACache get(Context ctx, String cacheName) { - File f = new File(ctx.getCacheDir(), cacheName); - return get(f, MAX_SIZE, MAX_COUNT); - } - - public static ACache get(File cacheDir) { - return get(cacheDir, MAX_SIZE, MAX_COUNT); - } - - public static ACache get(Context ctx, long max_zise, int max_count) { - File f = new File(ctx.getCacheDir(), "ACache"); - return get(f, max_zise, max_count); - } - - public static ACache get(File cacheDir, long max_zise, int max_count) { - ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid()); - if (manager == null) { - manager = new ACache(cacheDir, max_zise, max_count); - mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager); - } - return manager; - } - - private static String myPid() { - return "_" + android.os.Process.myPid(); - } - - private ACache(File cacheDir, long max_size, int max_count) { - if (!cacheDir.exists() && !cacheDir.mkdirs()) { - throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath()); - } - mCache = new ACacheManager(cacheDir, max_size, max_count); - } - - /** - * Provides a means to save a cached file before the data are available. - * Since writing about the file is complete, and its close method is called, - * its contents will be registered in the cache. Example of use: - * - * ACache cache = new ACache(this) try { OutputStream stream = - * cache.put("myFileName") stream.write("some bytes".getBytes()); // now - * update cache! stream.close(); } catch(FileNotFoundException e){ - * e.printStackTrace() } - */ - class xFileOutputStream extends FileOutputStream { - File file; - - public xFileOutputStream(File file) throws FileNotFoundException { - super(file); - this.file = file; - } - - public void close() throws IOException { - super.close(); - mCache.put(file); - } - } - - // ======================================= - // ============ String数据 读写 ============== - // ======================================= - /** - * 保存 String数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的String数据 - */ - public void put(String key, String value) { - File file = mCache.newFile(key); - BufferedWriter out = null; - try { - out = new BufferedWriter(new FileWriter(file), 1024); - out.write(value); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (out != null) { - try { - out.flush(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - mCache.put(file); - } - } - - /** - * 保存 String数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的String数据 - * @param saveTime - * 保存的时间,单位:秒 - */ - public void put(String key, String value, int saveTime) { - put(key, Utils.newStringWithDateInfo(saveTime, value)); - } - - /** - * 读取 String数据 - * - * @param key - * @return String 数据 - */ - public String getAsString(String key) { - File file = mCache.get(key); - if (!file.exists()) - return null; - boolean removeFile = false; - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(file)); - String readString = ""; - String currentLine; - while ((currentLine = in.readLine()) != null) { - readString += currentLine; - } - if (!Utils.isDue(readString)) { - return Utils.clearDateInfo(readString); - } else { - removeFile = true; - return null; - } - } catch (IOException e) { - e.printStackTrace(); - return null; - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (removeFile) - remove(key); - } - } - - // ======================================= - // ============= JSONObject 数据 读写 ============== - // ======================================= - /** - * 保存 JSONObject数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的JSON数据 - */ - public void put(String key, JSONObject value) { - put(key, value.toString()); - } - - /** - * 保存 JSONObject数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的JSONObject数据 - * @param saveTime - * 保存的时间,单位:秒 - */ - public void put(String key, JSONObject value, int saveTime) { - put(key, value.toString(), saveTime); - } - - /** - * 读取JSONObject数据 - * - * @param key - * @return JSONObject数据 - */ - public JSONObject getAsJSONObject(String key) { - String JSONString = getAsString(key); - try { - JSONObject obj = new JSONObject(JSONString); - return obj; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - // ======================================= - // ============ JSONArray 数据 读写 ============= - // ======================================= - /** - * 保存 JSONArray数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的JSONArray数据 - */ - public void put(String key, JSONArray value) { - put(key, value.toString()); - } - - /** - * 保存 JSONArray数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的JSONArray数据 - * @param saveTime - * 保存的时间,单位:秒 - */ - public void put(String key, JSONArray value, int saveTime) { - put(key, value.toString(), saveTime); - } - - /** - * 读取JSONArray数据 - * - * @param key - * @return JSONArray数据 - */ - public JSONArray getAsJSONArray(String key) { - String JSONString = getAsString(key); - try { - JSONArray obj = new JSONArray(JSONString); - return obj; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - // ======================================= - // ============== byte 数据 读写 ============= - // ======================================= - /** - * 保存 byte数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的数据 - */ - public void put(String key, byte[] value) { - File file = mCache.newFile(key); - FileOutputStream out = null; - try { - out = new FileOutputStream(file); - out.write(value); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (out != null) { - try { - out.flush(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - mCache.put(file); - } - } - - /** - * Cache for a stream - * - * @param key - * the file name. - * @return OutputStream stream for writing data. - * @throws FileNotFoundException - * if the file can not be created. - */ - public OutputStream put(String key) throws FileNotFoundException { - return new xFileOutputStream(mCache.newFile(key)); - } - - /** - * - * @param key - * the file name. - * @return (InputStream or null) stream previously saved in cache. - * @throws FileNotFoundException - * if the file can not be opened - */ - public InputStream get(String key) throws FileNotFoundException { - File file = mCache.get(key); - if (!file.exists()) - return null; - return new FileInputStream(file); - } - - /** - * 保存 byte数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的数据 - * @param saveTime - * 保存的时间,单位:秒 - */ - public void put(String key, byte[] value, int saveTime) { - put(key, Utils.newByteArrayWithDateInfo(saveTime, value)); - } - - /** - * 获取 byte 数据 - * - * @param key - * @return byte 数据 - */ - public byte[] getAsBinary(String key) { - RandomAccessFile RAFile = null; - boolean removeFile = false; - try { - File file = mCache.get(key); - if (!file.exists()) - return null; - RAFile = new RandomAccessFile(file, "r"); - byte[] byteArray = new byte[(int) RAFile.length()]; - RAFile.read(byteArray); - if (!Utils.isDue(byteArray)) { - return Utils.clearDateInfo(byteArray); - } else { - removeFile = true; - return null; - } - } catch (Exception e) { - e.printStackTrace(); - return null; - } finally { - if (RAFile != null) { - try { - RAFile.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (removeFile) - remove(key); - } - } - - // ======================================= - // ============= 序列化 数据 读写 =============== - // ======================================= - /** - * 保存 Serializable数据 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的value - */ - public void put(String key, Serializable value) { - put(key, value, -1); - } - - /** - * 保存 Serializable数据到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的value - * @param saveTime - * 保存的时间,单位:秒 - */ - public void put(String key, Serializable value, int saveTime) { - ByteArrayOutputStream baos = null; - ObjectOutputStream oos = null; - try { - baos = new ByteArrayOutputStream(); - oos = new ObjectOutputStream(baos); - oos.writeObject(value); - byte[] data = baos.toByteArray(); - if (saveTime != -1) { - put(key, data, saveTime); - } else { - put(key, data); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - oos.close(); - } catch (IOException e) { - } - } - } - - /** - * 读取 Serializable数据 - * - * @param key - * @return Serializable 数据 - */ - public Object getAsObject(String key) { - byte[] data = getAsBinary(key); - if (data != null) { - ByteArrayInputStream bais = null; - ObjectInputStream ois = null; - try { - bais = new ByteArrayInputStream(data); - ois = new ObjectInputStream(bais); - Object reObject = ois.readObject(); - return reObject; - } catch (Exception e) { - e.printStackTrace(); - return null; - } finally { - try { - if (bais != null) - bais.close(); - } catch (IOException e) { - e.printStackTrace(); - } - try { - if (ois != null) - ois.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return null; - - } - - // ======================================= - // ============== bitmap 数据 读写 ============= - // ======================================= - /** - * 保存 bitmap 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的bitmap数据 - */ - public void put(String key, Bitmap value) { - put(key, Utils.Bitmap2Bytes(value)); - } - - /** - * 保存 bitmap 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的 bitmap 数据 - * @param saveTime - * 保存的时间,单位:秒 - */ - public void put(String key, Bitmap value, int saveTime) { - put(key, Utils.Bitmap2Bytes(value), saveTime); - } - - /** - * 读取 bitmap 数据 - * - * @param key - * @return bitmap 数据 - */ - public Bitmap getAsBitmap(String key) { - if (getAsBinary(key) == null) { - return null; - } - return Utils.Bytes2Bimap(getAsBinary(key)); - } - - // ======================================= - // ============= drawable 数据 读写 ============= - // ======================================= - /** - * 保存 drawable 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的drawable数据 - */ - public void put(String key, Drawable value) { - put(key, Utils.drawable2Bitmap(value)); - } - - /** - * 保存 drawable 到 缓存中 - * - * @param key - * 保存的key - * @param value - * 保存的 drawable 数据 - * @param saveTime - * 保存的时间,单位:秒 - */ - public void put(String key, Drawable value, int saveTime) { - put(key, Utils.drawable2Bitmap(value), saveTime); - } - - /** - * 读取 Drawable 数据 - * - * @param key - * @return Drawable 数据 - */ - public Drawable getAsDrawable(String key) { - if (getAsBinary(key) == null) { - return null; - } - return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key))); - } - - /** - * 获取缓存文件 - * - * @param key - * @return value 缓存的文件 - */ - public File file(String key) { - File f = mCache.newFile(key); - if (f.exists()) - return f; - return null; - } - - /** - * 移除某个key - * - * @param key - * @return 是否移除成功 - */ - public boolean remove(String key) { - return mCache.remove(key); - } - - /** - * 清除所有数据 - */ - public void clear() { - mCache.clear(); - } - - /** - * @title 缓存管理器 - * @author 杨福海(michael) www.yangfuhai.com - * @version 1.0 - */ - public class ACacheManager { - private final AtomicLong cacheSize; - private final AtomicInteger cacheCount; - private final long sizeLimit; - private final int countLimit; - private final Map lastUsageDates = Collections.synchronizedMap(new HashMap()); - protected File cacheDir; - - private ACacheManager(File cacheDir, long sizeLimit, int countLimit) { - this.cacheDir = cacheDir; - this.sizeLimit = sizeLimit; - this.countLimit = countLimit; - cacheSize = new AtomicLong(); - cacheCount = new AtomicInteger(); - calculateCacheSizeAndCacheCount(); - } - - /** - * 计算 cacheSize和cacheCount - */ - private void calculateCacheSizeAndCacheCount() { - new Thread(new Runnable() { - @Override - public void run() { - int size = 0; - int count = 0; - File[] cachedFiles = cacheDir.listFiles(); - if (cachedFiles != null) { - for (File cachedFile : cachedFiles) { - size += calculateSize(cachedFile); - count += 1; - lastUsageDates.put(cachedFile, cachedFile.lastModified()); - } - cacheSize.set(size); - cacheCount.set(count); - } - } - }).start(); - } - - private void put(File file) { - int curCacheCount = cacheCount.get(); - while (curCacheCount + 1 > countLimit) { - long freedSize = removeNext(); - cacheSize.addAndGet(-freedSize); - - curCacheCount = cacheCount.addAndGet(-1); - } - cacheCount.addAndGet(1); - - long valueSize = calculateSize(file); - long curCacheSize = cacheSize.get(); - while (curCacheSize + valueSize > sizeLimit) { - long freedSize = removeNext(); - curCacheSize = cacheSize.addAndGet(-freedSize); - } - cacheSize.addAndGet(valueSize); - - Long currentTime = System.currentTimeMillis(); - file.setLastModified(currentTime); - lastUsageDates.put(file, currentTime); - } - - private File get(String key) { - File file = newFile(key); - Long currentTime = System.currentTimeMillis(); - file.setLastModified(currentTime); - lastUsageDates.put(file, currentTime); - - return file; - } - - private File newFile(String key) { - return new File(cacheDir, key.hashCode() + ""); - } - - private boolean remove(String key) { - File image = get(key); - return image.delete(); - } - - private void clear() { - lastUsageDates.clear(); - cacheSize.set(0); - File[] files = cacheDir.listFiles(); - if (files != null) { - for (File f : files) { - f.delete(); - } - } - } - - /** - * 移除旧的文件 - * - * @return - */ - private long removeNext() { - if (lastUsageDates.isEmpty()) { - return 0; - } - - Long oldestUsage = null; - File mostLongUsedFile = null; - Set> entries = lastUsageDates.entrySet(); - synchronized (lastUsageDates) { - for (Entry entry : entries) { - if (mostLongUsedFile == null) { - mostLongUsedFile = entry.getKey(); - oldestUsage = entry.getValue(); - } else { - Long lastValueUsage = entry.getValue(); - if (lastValueUsage < oldestUsage) { - oldestUsage = lastValueUsage; - mostLongUsedFile = entry.getKey(); - } - } - } - } - - long fileSize = calculateSize(mostLongUsedFile); - if (mostLongUsedFile.delete()) { - lastUsageDates.remove(mostLongUsedFile); - } - return fileSize; - } - - private long calculateSize(File file) { - return file.length(); - } - } - - /** - * @title 时间计算工具类 - * @author 杨福海(michael) www.yangfuhai.com - * @version 1.0 - */ - private static class Utils { - - /** - * 判断缓存的String数据是否到期 - * - * @param str - * @return true:到期了 false:还没有到期 - */ - private static boolean isDue(String str) { - return isDue(str.getBytes()); - } - - /** - * 判断缓存的byte数据是否到期 - * - * @param data - * @return true:到期了 false:还没有到期 - */ - private static boolean isDue(byte[] data) { - String[] strs = getDateInfoFromDate(data); - if (strs != null && strs.length == 2) { - String saveTimeStr = strs[0]; - while (saveTimeStr.startsWith("0")) { - saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length()); - } - long saveTime = Long.valueOf(saveTimeStr); - long deleteAfter = Long.valueOf(strs[1]); - if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) { - return true; - } - } - return false; - } - - private static String newStringWithDateInfo(int second, String strInfo) { - return createDateInfo(second) + strInfo; - } - - private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) { - byte[] data1 = createDateInfo(second).getBytes(); - byte[] retdata = new byte[data1.length + data2.length]; - System.arraycopy(data1, 0, retdata, 0, data1.length); - System.arraycopy(data2, 0, retdata, data1.length, data2.length); - return retdata; - } - - private static String clearDateInfo(String strInfo) { - if (strInfo != null && hasDateInfo(strInfo.getBytes())) { - strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, strInfo.length()); - } - return strInfo; - } - - private static byte[] clearDateInfo(byte[] data) { - if (hasDateInfo(data)) { - return copyOfRange(data, indexOf(data, mSeparator) + 1, data.length); - } - return data; - } - - private static boolean hasDateInfo(byte[] data) { - return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14; - } - - private static String[] getDateInfoFromDate(byte[] data) { - if (hasDateInfo(data)) { - String saveDate = new String(copyOfRange(data, 0, 13)); - String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator))); - return new String[] { saveDate, deleteAfter }; - } - return null; - } - - private static int indexOf(byte[] data, char c) { - for (int i = 0; i < data.length; i++) { - if (data[i] == c) { - return i; - } - } - return -1; - } - - private static byte[] copyOfRange(byte[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) - throw new IllegalArgumentException(from + " > " + to); - byte[] copy = new byte[newLength]; - System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); - return copy; - } - - private static final char mSeparator = ' '; - - private static String createDateInfo(int second) { - String currentTime = System.currentTimeMillis() + ""; - while (currentTime.length() < 13) { - currentTime = "0" + currentTime; - } - return currentTime + "-" + second + mSeparator; - } - - /* - * Bitmap → byte[] - */ - private static byte[] Bitmap2Bytes(Bitmap bm) { - if (bm == null) { - return null; - } - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - bm.compress(Bitmap.CompressFormat.PNG, 100, baos); - return baos.toByteArray(); - } - - /* - * byte[] → Bitmap - */ - private static Bitmap Bytes2Bimap(byte[] b) { - if (b.length == 0) { - return null; - } - return BitmapFactory.decodeByteArray(b, 0, b.length); - } - - /* - * Drawable → Bitmap - */ - private static Bitmap drawable2Bitmap(Drawable drawable) { - if (drawable == null) { - return null; - } - // 取 drawable 的长宽 - int w = drawable.getIntrinsicWidth(); - int h = drawable.getIntrinsicHeight(); - // 取 drawable 的颜色格式 - Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; - // 建立对应 bitmap - Bitmap bitmap = Bitmap.createBitmap(w, h, config); - // 建立对应 bitmap 的画布 - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, w, h); - // 把 drawable 内容画到画布中 - drawable.draw(canvas); - return bitmap; - } - - /* - * Bitmap → Drawable - */ - @SuppressWarnings("deprecation") - private static Drawable bitmap2Drawable(Bitmap bm) { - if (bm == null) { - return null; - } - BitmapDrawable bd=new BitmapDrawable(bm); - bd.setTargetDensity(bm.getDensity()); - return new BitmapDrawable(bm); - } - } - -} diff --git a/app/src/main/java/com/maning/gankmm/utils/CacheDiskUtils.java b/app/src/main/java/com/maning/gankmm/utils/CacheDiskUtils.java new file mode 100644 index 0000000..5b6fe48 --- /dev/null +++ b/app/src/main/java/com/maning/gankmm/utils/CacheDiskUtils.java @@ -0,0 +1,1147 @@ +package com.maning.gankmm.utils; + +import android.annotation.SuppressLint; +import android.app.Application; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import androidx.annotation.NonNull; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.RandomAccessFile; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +/** + * @author : maning + * @date : 2020-04-26 + * @desc : + */ +public class CacheDiskUtils { + + private static Application sApplication; + + public static void init(Application application) { + sApplication = application; + } + + /** + * Return the context of Application object. + * + * @return the context of Application object + */ + public static Application getApp() { + if (sApplication != null) { + return sApplication; + } + Application app = getApplicationByReflect(); + init(app); + return app; + } + + private static Application getApplicationByReflect() { + try { + @SuppressLint("PrivateApi") + Class activityThread = Class.forName("android.app.ActivityThread"); + Object thread = activityThread.getMethod("currentActivityThread").invoke(null); + Object app = activityThread.getMethod("getApplication").invoke(thread); + if (app == null) { + throw new NullPointerException("u should init first"); + } + return (Application) app; + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + throw new NullPointerException("u should init first"); + } + + private static final long DEFAULT_MAX_SIZE = Long.MAX_VALUE; + private static final int DEFAULT_MAX_COUNT = Integer.MAX_VALUE; + private static final String CACHE_PREFIX = "cdu_"; + private static final String TYPE_BYTE = "by_"; + private static final String TYPE_STRING = "st_"; + private static final String TYPE_JSON_OBJECT = "jo_"; + private static final String TYPE_JSON_ARRAY = "ja_"; + private static final String TYPE_BITMAP = "bi_"; + private static final String TYPE_DRAWABLE = "dr_"; + private static final String TYPE_PARCELABLE = "pa_"; + private static final String TYPE_SERIALIZABLE = "se_"; + + private static final Map CACHE_MAP = new HashMap<>(); + + private final String mCacheKey; + private final File mCacheDir; + private final long mMaxSize; + private final int mMaxCount; + private DiskCacheManager mDiskCacheManager; + + /** + * Return the single {@link CacheDiskUtils} instance. + *

cache directory: /data/data/package/cache/cacheUtils

+ *

cache size: unlimited

+ *

cache count: unlimited

+ * + * @return the single {@link CacheDiskUtils} instance + */ + public static CacheDiskUtils getInstance() { + return getInstance("", DEFAULT_MAX_SIZE, DEFAULT_MAX_COUNT); + } + + /** + * Return the single {@link CacheDiskUtils} instance. + *

cache directory: /data/data/package/cache/cacheUtils

+ *

cache size: unlimited

+ *

cache count: unlimited

+ * + * @param cacheName The name of cache. + * @return the single {@link CacheDiskUtils} instance + */ + public static CacheDiskUtils getInstance(final String cacheName) { + return getInstance(cacheName, DEFAULT_MAX_SIZE, DEFAULT_MAX_COUNT); + } + + /** + * Return the single {@link CacheDiskUtils} instance. + *

cache directory: /data/data/package/cache/cacheUtils

+ * + * @param maxSize The max size of cache, in bytes. + * @param maxCount The max count of cache. + * @return the single {@link CacheDiskUtils} instance + */ + public static CacheDiskUtils getInstance(final long maxSize, final int maxCount) { + return getInstance("", maxSize, maxCount); + } + + /** + * Return the single {@link CacheDiskUtils} instance. + *

cache directory: /data/data/package/cache/cacheName

+ * + * @param cacheName The name of cache. + * @param maxSize The max size of cache, in bytes. + * @param maxCount The max count of cache. + * @return the single {@link CacheDiskUtils} instance + */ + public static CacheDiskUtils getInstance(String cacheName, final long maxSize, final int maxCount) { + if (isSpace(cacheName)) cacheName = "cacheUtils"; + File file = new File(getApp().getCacheDir(), cacheName); + return getInstance(file, maxSize, maxCount); + } + + /** + * Return the single {@link CacheDiskUtils} instance. + *

cache size: unlimited

+ *

cache count: unlimited

+ * + * @param cacheDir The directory of cache. + * @return the single {@link CacheDiskUtils} instance + */ + public static CacheDiskUtils getInstance(@NonNull final File cacheDir) { + return getInstance(cacheDir, DEFAULT_MAX_SIZE, DEFAULT_MAX_COUNT); + } + + /** + * Return the single {@link CacheDiskUtils} instance. + * + * @param cacheDir The directory of cache. + * @param maxSize The max size of cache, in bytes. + * @param maxCount The max count of cache. + * @return the single {@link CacheDiskUtils} instance + */ + public static CacheDiskUtils getInstance(@NonNull final File cacheDir, + final long maxSize, + final int maxCount) { + final String cacheKey = cacheDir.getAbsoluteFile() + "_" + maxSize + "_" + maxCount; + CacheDiskUtils cache = CACHE_MAP.get(cacheKey); + if (cache == null) { + synchronized (CacheDiskUtils.class) { + cache = CACHE_MAP.get(cacheKey); + if (cache == null) { + cache = new CacheDiskUtils(cacheKey, cacheDir, maxSize, maxCount); + CACHE_MAP.put(cacheKey, cache); + } + } + } + return cache; + } + + private CacheDiskUtils(final String cacheKey, + final File cacheDir, + final long maxSize, + final int maxCount) { + mCacheKey = cacheKey; + mCacheDir = cacheDir; + mMaxSize = maxSize; + mMaxCount = maxCount; + } + + private DiskCacheManager getDiskCacheManager() { + if (mCacheDir.exists()) { + if (mDiskCacheManager == null) { + mDiskCacheManager = new DiskCacheManager(mCacheDir, mMaxSize, mMaxCount); + } + } else { + if (mCacheDir.mkdirs()) { + mDiskCacheManager = new DiskCacheManager(mCacheDir, mMaxSize, mMaxCount); + } else { + Log.e("CacheDiskUtils", "can't make dirs in " + mCacheDir.getAbsolutePath()); + } + } + return mDiskCacheManager; + } + + @Override + public String toString() { + return mCacheKey + "@" + Integer.toHexString(hashCode()); + } + + /////////////////////////////////////////////////////////////////////////// + // about bytes + /////////////////////////////////////////////////////////////////////////// + + /** + * Put bytes in cache. + * + * @param key The key of cache. + * @param value The value of cache. + */ + public void put(@NonNull final String key, final byte[] value) { + put(key, value, -1); + } + + /** + * Put bytes in cache. + * + * @param key The key of cache. + * @param value The value of cache. + * @param saveTime The save time of cache, in seconds. + */ + public void put(@NonNull final String key, final byte[] value, final int saveTime) { + realPutBytes(TYPE_BYTE + key, value, saveTime); + } + + private void realPutBytes(final String key, byte[] value, int saveTime) { + if (value == null) return; + DiskCacheManager diskCacheManager = getDiskCacheManager(); + if (diskCacheManager == null) return; + if (saveTime >= 0) value = DiskCacheHelper.newByteArrayWithTime(saveTime, value); + File file = diskCacheManager.getFileBeforePut(key); + writeFileFromBytes(file, value); + diskCacheManager.updateModify(file); + diskCacheManager.put(file); + } + + + /** + * Return the bytes in cache. + * + * @param key The key of cache. + * @return the bytes if cache exists or null otherwise + */ + public byte[] getBytes(@NonNull final String key) { + return getBytes(key, null); + } + + /** + * Return the bytes in cache. + * + * @param key The key of cache. + * @param defaultValue The default value if the cache doesn't exist. + * @return the bytes if cache exists or defaultValue otherwise + */ + public byte[] getBytes(@NonNull final String key, final byte[] defaultValue) { + return realGetBytes(TYPE_BYTE + key, defaultValue); + } + + private byte[] realGetBytes(@NonNull final String key) { + return realGetBytes(key, null); + } + + private byte[] realGetBytes(@NonNull final String key, final byte[] defaultValue) { + DiskCacheManager diskCacheManager = getDiskCacheManager(); + if (diskCacheManager == null) return defaultValue; + final File file = diskCacheManager.getFileIfExists(key); + if (file == null) return defaultValue; + byte[] data = readFile2Bytes(file); + if (DiskCacheHelper.isDue(data)) { + diskCacheManager.removeByKey(key); + return defaultValue; + } + diskCacheManager.updateModify(file); + return DiskCacheHelper.getDataWithoutDueTime(data); + } + + /////////////////////////////////////////////////////////////////////////// + // about String + /////////////////////////////////////////////////////////////////////////// + + /** + * Put string value in cache. + * + * @param key The key of cache. + * @param value The value of cache. + */ + public void put(@NonNull final String key, final String value) { + put(key, value, -1); + } + + /** + * Put string value in cache. + * + * @param key The key of cache. + * @param value The value of cache. + * @param saveTime The save time of cache, in seconds. + */ + public void put(@NonNull final String key, final String value, final int saveTime) { + realPutBytes(TYPE_STRING + key, string2Bytes(value), saveTime); + } + + /** + * Return the string value in cache. + * + * @param key The key of cache. + * @return the string value if cache exists or null otherwise + */ + public String getString(@NonNull final String key) { + return getString(key, null); + } + + /** + * Return the string value in cache. + * + * @param key The key of cache. + * @param defaultValue The default value if the cache doesn't exist. + * @return the string value if cache exists or defaultValue otherwise + */ + public String getString(@NonNull final String key, final String defaultValue) { + byte[] bytes = realGetBytes(TYPE_STRING + key); + if (bytes == null) return defaultValue; + return bytes2String(bytes); + } + + /////////////////////////////////////////////////////////////////////////// + // about JSONObject + /////////////////////////////////////////////////////////////////////////// + + /** + * Put JSONObject in cache. + * + * @param key The key of cache. + * @param value The value of cache. + */ + public void put(@NonNull final String key, final JSONObject value) { + put(key, value, -1); + } + + /** + * Put JSONObject in cache. + * + * @param key The key of cache. + * @param value The value of cache. + * @param saveTime The save time of cache, in seconds. + */ + public void put(@NonNull final String key, + final JSONObject value, + final int saveTime) { + realPutBytes(TYPE_JSON_OBJECT + key, jsonObject2Bytes(value), saveTime); + } + + /** + * Return the JSONObject in cache. + * + * @param key The key of cache. + * @return the JSONObject if cache exists or null otherwise + */ + public JSONObject getJSONObject(@NonNull final String key) { + return getJSONObject(key, null); + } + + /** + * Return the JSONObject in cache. + * + * @param key The key of cache. + * @param defaultValue The default value if the cache doesn't exist. + * @return the JSONObject if cache exists or defaultValue otherwise + */ + public JSONObject getJSONObject(@NonNull final String key, final JSONObject defaultValue) { + byte[] bytes = realGetBytes(TYPE_JSON_OBJECT + key); + if (bytes == null) return defaultValue; + return bytes2JSONObject(bytes); + } + + + /////////////////////////////////////////////////////////////////////////// + // about JSONArray + /////////////////////////////////////////////////////////////////////////// + + /** + * Put JSONArray in cache. + * + * @param key The key of cache. + * @param value The value of cache. + */ + public void put(@NonNull final String key, final JSONArray value) { + put(key, value, -1); + } + + /** + * Put JSONArray in cache. + * + * @param key The key of cache. + * @param value The value of cache. + * @param saveTime The save time of cache, in seconds. + */ + public void put(@NonNull final String key, final JSONArray value, final int saveTime) { + realPutBytes(TYPE_JSON_ARRAY + key, jsonArray2Bytes(value), saveTime); + } + + /** + * Return the JSONArray in cache. + * + * @param key The key of cache. + * @return the JSONArray if cache exists or null otherwise + */ + public JSONArray getJSONArray(@NonNull final String key) { + return getJSONArray(key, null); + } + + /** + * Return the JSONArray in cache. + * + * @param key The key of cache. + * @param defaultValue The default value if the cache doesn't exist. + * @return the JSONArray if cache exists or defaultValue otherwise + */ + public JSONArray getJSONArray(@NonNull final String key, final JSONArray defaultValue) { + byte[] bytes = realGetBytes(TYPE_JSON_ARRAY + key); + if (bytes == null) return defaultValue; + return bytes2JSONArray(bytes); + } + + + /////////////////////////////////////////////////////////////////////////// + // about Bitmap + /////////////////////////////////////////////////////////////////////////// + + /** + * Put bitmap in cache. + * + * @param key The key of cache. + * @param value The value of cache. + */ + public void put(@NonNull final String key, final Bitmap value) { + put(key, value, -1); + } + + /** + * Put bitmap in cache. + * + * @param key The key of cache. + * @param value The value of cache. + * @param saveTime The save time of cache, in seconds. + */ + public void put(@NonNull final String key, final Bitmap value, final int saveTime) { + realPutBytes(TYPE_BITMAP + key, bitmap2Bytes(value), saveTime); + } + + /** + * Return the bitmap in cache. + * + * @param key The key of cache. + * @return the bitmap if cache exists or null otherwise + */ + public Bitmap getBitmap(@NonNull final String key) { + return getBitmap(key, null); + } + + /** + * Return the bitmap in cache. + * + * @param key The key of cache. + * @param defaultValue The default value if the cache doesn't exist. + * @return the bitmap if cache exists or defaultValue otherwise + */ + public Bitmap getBitmap(@NonNull final String key, final Bitmap defaultValue) { + byte[] bytes = realGetBytes(TYPE_BITMAP + key); + if (bytes == null) return defaultValue; + return bytes2Bitmap(bytes); + } + + /////////////////////////////////////////////////////////////////////////// + // about Drawable + /////////////////////////////////////////////////////////////////////////// + + /** + * Put drawable in cache. + * + * @param key The key of cache. + * @param value The value of cache. + */ + public void put(@NonNull final String key, final Drawable value) { + put(key, value, -1); + } + + /** + * Put drawable in cache. + * + * @param key The key of cache. + * @param value The value of cache. + * @param saveTime The save time of cache, in seconds. + */ + public void put(@NonNull final String key, final Drawable value, final int saveTime) { + realPutBytes(TYPE_DRAWABLE + key, drawable2Bytes(value), saveTime); + } + + /** + * Return the drawable in cache. + * + * @param key The key of cache. + * @return the drawable if cache exists or null otherwise + */ + public Drawable getDrawable(@NonNull final String key) { + return getDrawable(key, null); + } + + /** + * Return the drawable in cache. + * + * @param key The key of cache. + * @param defaultValue The default value if the cache doesn't exist. + * @return the drawable if cache exists or defaultValue otherwise + */ + public Drawable getDrawable(@NonNull final String key, final Drawable defaultValue) { + byte[] bytes = realGetBytes(TYPE_DRAWABLE + key); + if (bytes == null) return defaultValue; + return bytes2Drawable(bytes); + } + + /////////////////////////////////////////////////////////////////////////// + // about Parcelable + /////////////////////////////////////////////////////////////////////////// + + /** + * Put parcelable in cache. + * + * @param key The key of cache. + * @param value The value of cache. + */ + public void put(@NonNull final String key, final Parcelable value) { + put(key, value, -1); + } + + /** + * Put parcelable in cache. + * + * @param key The key of cache. + * @param value The value of cache. + * @param saveTime The save time of cache, in seconds. + */ + public void put(@NonNull final String key, final Parcelable value, final int saveTime) { + realPutBytes(TYPE_PARCELABLE + key, parcelable2Bytes(value), saveTime); + } + + /** + * Return the parcelable in cache. + * + * @param key The key of cache. + * @param creator The creator. + * @param The value type. + * @return the parcelable if cache exists or null otherwise + */ + public T getParcelable(@NonNull final String key, + @NonNull final Parcelable.Creator creator) { + return getParcelable(key, creator, null); + } + + /** + * Return the parcelable in cache. + * + * @param key The key of cache. + * @param creator The creator. + * @param defaultValue The default value if the cache doesn't exist. + * @param The value type. + * @return the parcelable if cache exists or defaultValue otherwise + */ + public T getParcelable(@NonNull final String key, + @NonNull final Parcelable.Creator creator, + final T defaultValue) { + byte[] bytes = realGetBytes(TYPE_PARCELABLE + key); + if (bytes == null) return defaultValue; + return bytes2Parcelable(bytes, creator); + } + + /////////////////////////////////////////////////////////////////////////// + // about Serializable + /////////////////////////////////////////////////////////////////////////// + + /** + * Put serializable in cache. + * + * @param key The key of cache. + * @param value The value of cache. + */ + public void put(@NonNull final String key, final Serializable value) { + put(key, value, -1); + } + + /** + * Put serializable in cache. + * + * @param key The key of cache. + * @param value The value of cache. + * @param saveTime The save time of cache, in seconds. + */ + public void put(@NonNull final String key, final Serializable value, final int saveTime) { + realPutBytes(TYPE_SERIALIZABLE + key, serializable2Bytes(value), saveTime); + } + + /** + * Return the serializable in cache. + * + * @param key The key of cache. + * @return the bitmap if cache exists or null otherwise + */ + public Object getSerializable(@NonNull final String key) { + return getSerializable(key, null); + } + + /** + * Return the serializable in cache. + * + * @param key The key of cache. + * @param defaultValue The default value if the cache doesn't exist. + * @return the bitmap if cache exists or defaultValue otherwise + */ + public Object getSerializable(@NonNull final String key, final Object defaultValue) { + byte[] bytes = realGetBytes(TYPE_SERIALIZABLE + key); + if (bytes == null) return defaultValue; + return bytes2Object(bytes); + } + + /** + * Return the size of cache, in bytes. + * + * @return the size of cache, in bytes + */ + public long getCacheSize() { + DiskCacheManager diskCacheManager = getDiskCacheManager(); + if (diskCacheManager == null) return 0; + return diskCacheManager.getCacheSize(); + } + + /** + * Return the count of cache. + * + * @return the count of cache + */ + public int getCacheCount() { + DiskCacheManager diskCacheManager = getDiskCacheManager(); + if (diskCacheManager == null) return 0; + return diskCacheManager.getCacheCount(); + } + + /** + * Remove the cache by key. + * + * @param key The key of cache. + * @return {@code true}: success
{@code false}: fail + */ + public boolean remove(@NonNull final String key) { + DiskCacheManager diskCacheManager = getDiskCacheManager(); + if (diskCacheManager == null) return true; + return diskCacheManager.removeByKey(TYPE_BYTE + key) + && diskCacheManager.removeByKey(TYPE_STRING + key) + && diskCacheManager.removeByKey(TYPE_JSON_OBJECT + key) + && diskCacheManager.removeByKey(TYPE_JSON_ARRAY + key) + && diskCacheManager.removeByKey(TYPE_BITMAP + key) + && diskCacheManager.removeByKey(TYPE_DRAWABLE + key) + && diskCacheManager.removeByKey(TYPE_PARCELABLE + key) + && diskCacheManager.removeByKey(TYPE_SERIALIZABLE + key); + } + + /** + * Clear all of the cache. + * + * @return {@code true}: success
{@code false}: fail + */ + public boolean clear() { + DiskCacheManager diskCacheManager = getDiskCacheManager(); + if (diskCacheManager == null) return true; + return diskCacheManager.clear(); + } + + private static final class DiskCacheManager { + private final AtomicLong cacheSize; + private final AtomicInteger cacheCount; + private final long sizeLimit; + private final int countLimit; + private final Map lastUsageDates + = Collections.synchronizedMap(new HashMap()); + private final File cacheDir; + private final Thread mThread; + + private DiskCacheManager(final File cacheDir, final long sizeLimit, final int countLimit) { + this.cacheDir = cacheDir; + this.sizeLimit = sizeLimit; + this.countLimit = countLimit; + cacheSize = new AtomicLong(); + cacheCount = new AtomicInteger(); + mThread = new Thread(new Runnable() { + @Override + public void run() { + int size = 0; + int count = 0; + final File[] cachedFiles = cacheDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.startsWith(CACHE_PREFIX); + } + }); + if (cachedFiles != null) { + for (File cachedFile : cachedFiles) { + size += cachedFile.length(); + count += 1; + lastUsageDates.put(cachedFile, cachedFile.lastModified()); + } + cacheSize.getAndAdd(size); + cacheCount.getAndAdd(count); + } + } + }); + mThread.start(); + } + + private long getCacheSize() { + wait2InitOk(); + return cacheSize.get(); + } + + private int getCacheCount() { + wait2InitOk(); + return cacheCount.get(); + } + + private File getFileBeforePut(final String key) { + wait2InitOk(); + File file = new File(cacheDir, getCacheNameByKey(key)); + if (file.exists()) { + cacheCount.addAndGet(-1); + cacheSize.addAndGet(-file.length()); + } + return file; + } + + private void wait2InitOk() { + try { + mThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private File getFileIfExists(final String key) { + File file = new File(cacheDir, getCacheNameByKey(key)); + if (!file.exists()) return null; + return file; + } + + private String getCacheNameByKey(final String key) { + return CACHE_PREFIX + key.substring(0, 3) + key.substring(3).hashCode(); + } + + private void put(final File file) { + cacheCount.addAndGet(1); + cacheSize.addAndGet(file.length()); + while (cacheCount.get() > countLimit || cacheSize.get() > sizeLimit) { + cacheSize.addAndGet(-removeOldest()); + cacheCount.addAndGet(-1); + } + } + + private void updateModify(final File file) { + Long millis = System.currentTimeMillis(); + file.setLastModified(millis); + lastUsageDates.put(file, millis); + } + + private boolean removeByKey(final String key) { + File file = getFileIfExists(key); + if (file == null) return true; + if (!file.delete()) return false; + cacheSize.addAndGet(-file.length()); + cacheCount.addAndGet(-1); + lastUsageDates.remove(file); + return true; + } + + private boolean clear() { + File[] files = cacheDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.startsWith(CACHE_PREFIX); + } + }); + if (files == null || files.length <= 0) return true; + boolean flag = true; + for (File file : files) { + if (!file.delete()) { + flag = false; + continue; + } + cacheSize.addAndGet(-file.length()); + cacheCount.addAndGet(-1); + lastUsageDates.remove(file); + } + if (flag) { + lastUsageDates.clear(); + cacheSize.set(0); + cacheCount.set(0); + } + return flag; + } + + /** + * Remove the oldest files. + * + * @return the size of oldest files, in bytes + */ + private long removeOldest() { + if (lastUsageDates.isEmpty()) return 0; + Long oldestUsage = Long.MAX_VALUE; + File oldestFile = null; + Set> entries = lastUsageDates.entrySet(); + synchronized (lastUsageDates) { + for (Map.Entry entry : entries) { + Long lastValueUsage = entry.getValue(); + if (lastValueUsage < oldestUsage) { + oldestUsage = lastValueUsage; + oldestFile = entry.getKey(); + } + } + } + if (oldestFile == null) return 0; + long fileSize = oldestFile.length(); + if (oldestFile.delete()) { + lastUsageDates.remove(oldestFile); + return fileSize; + } + return 0; + } + } + + private static final class DiskCacheHelper { + + static final int TIME_INFO_LEN = 14; + + private static byte[] newByteArrayWithTime(final int second, final byte[] data) { + byte[] time = createDueTime(second).getBytes(); + byte[] content = new byte[time.length + data.length]; + System.arraycopy(time, 0, content, 0, time.length); + System.arraycopy(data, 0, content, time.length, data.length); + return content; + } + + /** + * Return the string of due time. + * + * @param seconds The seconds. + * @return the string of due time + */ + private static String createDueTime(final int seconds) { + return String.format( + Locale.getDefault(), "_$%010d$_", + System.currentTimeMillis() / 1000 + seconds + ); + } + + private static boolean isDue(final byte[] data) { + long millis = getDueTime(data); + return millis != -1 && System.currentTimeMillis() > millis; + } + + private static long getDueTime(final byte[] data) { + if (hasTimeInfo(data)) { + String millis = new String(copyOfRange(data, 2, 12)); + try { + return Long.parseLong(millis) * 1000; + } catch (NumberFormatException e) { + return -1; + } + } + return -1; + } + + private static byte[] getDataWithoutDueTime(final byte[] data) { + if (hasTimeInfo(data)) { + return copyOfRange(data, TIME_INFO_LEN, data.length); + } + return data; + } + + private static byte[] copyOfRange(final byte[] original, final int from, final int to) { + int newLength = to - from; + if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); + byte[] copy = new byte[newLength]; + System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); + return copy; + } + + private static boolean hasTimeInfo(final byte[] data) { + return data != null + && data.length >= TIME_INFO_LEN + && data[0] == '_' + && data[1] == '$' + && data[12] == '$' + && data[13] == '_'; + } + } + + /////////////////////////////////////////////////////////////////////////// + // other utils methods + /////////////////////////////////////////////////////////////////////////// + + private static byte[] string2Bytes(final String string) { + if (string == null) return null; + return string.getBytes(); + } + + private static String bytes2String(final byte[] bytes) { + if (bytes == null) return null; + return new String(bytes); + } + + private static byte[] jsonObject2Bytes(final JSONObject jsonObject) { + if (jsonObject == null) return null; + return jsonObject.toString().getBytes(); + } + + private static JSONObject bytes2JSONObject(final byte[] bytes) { + if (bytes == null) return null; + try { + return new JSONObject(new String(bytes)); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private static byte[] jsonArray2Bytes(final JSONArray jsonArray) { + if (jsonArray == null) return null; + return jsonArray.toString().getBytes(); + } + + private static JSONArray bytes2JSONArray(final byte[] bytes) { + if (bytes == null) return null; + try { + return new JSONArray(new String(bytes)); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private static byte[] parcelable2Bytes(final Parcelable parcelable) { + if (parcelable == null) return null; + Parcel parcel = Parcel.obtain(); + parcelable.writeToParcel(parcel, 0); + byte[] bytes = parcel.marshall(); + parcel.recycle(); + return bytes; + } + + private static T bytes2Parcelable(final byte[] bytes, + final Parcelable.Creator creator) { + if (bytes == null) return null; + Parcel parcel = Parcel.obtain(); + parcel.unmarshall(bytes, 0, bytes.length); + parcel.setDataPosition(0); + T result = creator.createFromParcel(parcel); + parcel.recycle(); + return result; + } + + private static byte[] serializable2Bytes(final Serializable serializable) { + if (serializable == null) return null; + ByteArrayOutputStream baos; + ObjectOutputStream oos = null; + try { + oos = new ObjectOutputStream(baos = new ByteArrayOutputStream()); + oos.writeObject(serializable); + return baos.toByteArray(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + try { + if (oos != null) { + oos.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private static Object bytes2Object(final byte[] bytes) { + if (bytes == null) return null; + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); + return ois.readObject(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + try { + if (ois != null) { + ois.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private static byte[] bitmap2Bytes(final Bitmap bitmap) { + if (bitmap == null) return null; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); + return baos.toByteArray(); + } + + private static Bitmap bytes2Bitmap(final byte[] bytes) { + return (bytes == null || bytes.length <= 0) + ? null + : BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + } + + private static byte[] drawable2Bytes(final Drawable drawable) { + return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable)); + } + + private static Drawable bytes2Drawable(final byte[] bytes) { + return bytes == null ? null : bitmap2Drawable(bytes2Bitmap(bytes)); + } + + private static Bitmap drawable2Bitmap(final Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + if (bitmapDrawable.getBitmap() != null) { + return bitmapDrawable.getBitmap(); + } + } + Bitmap bitmap; + if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { + bitmap = Bitmap.createBitmap( + 1, + 1, + drawable.getOpacity() != PixelFormat.OPAQUE + ? Bitmap.Config.ARGB_8888 + : Bitmap.Config.RGB_565 + ); + } else { + bitmap = Bitmap.createBitmap( + drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), + drawable.getOpacity() != PixelFormat.OPAQUE + ? Bitmap.Config.ARGB_8888 + : Bitmap.Config.RGB_565 + ); + } + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } + + private static Drawable bitmap2Drawable(final Bitmap bitmap) { + return bitmap == null + ? null + : new BitmapDrawable(getApp().getResources(), bitmap); + } + + + private static void writeFileFromBytes(final File file, final byte[] bytes) { + FileChannel fc = null; + try { + fc = new FileOutputStream(file, false).getChannel(); + fc.write(ByteBuffer.wrap(bytes)); + fc.force(true); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (fc != null) { + fc.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private static byte[] readFile2Bytes(final File file) { + FileChannel fc = null; + try { + fc = new RandomAccessFile(file, "r").getChannel(); + int size = (int) fc.size(); + MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, size).load(); + byte[] data = new byte[size]; + mbb.get(data, 0, size); + return data; + } catch (IOException e) { + e.printStackTrace(); + return null; + } finally { + try { + if (fc != null) { + fc.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private static boolean isSpace(final String s) { + if (s == null) return true; + for (int i = 0, len = s.length(); i < len; ++i) { + if (!Character.isWhitespace(s.charAt(i))) { + return false; + } + } + return true; + } +} diff --git a/app/src/main/java/com/maning/gankmm/utils/CacheManager.java b/app/src/main/java/com/maning/gankmm/utils/CacheManager.java new file mode 100644 index 0000000..3e78c1e --- /dev/null +++ b/app/src/main/java/com/maning/gankmm/utils/CacheManager.java @@ -0,0 +1,44 @@ +package com.maning.gankmm.utils; + +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author : maning + * @date : 2020-10-16 + * @desc : 缓存管理 + */ +public class CacheManager { + + private static final String KEY_SCAN_RESULT = "KEY_SCAN_RESULT"; + private static Gson gson = new Gson(); + + public static void saveScanResult(String content) { + List caches = new ArrayList<>(); + String cache = MMKVUtils.getInstance().getString(KEY_SCAN_RESULT, ""); + if (TextUtils.isEmpty(cache)) { + caches.add(content); + } else { + caches = gson.fromJson(cache, new TypeToken>() { + }.getType()); + caches.add(0,content); + } + MMKVUtils.getInstance().putString(KEY_SCAN_RESULT, gson.toJson(caches)); + } + + public static List getScanResult() { + String cache = MMKVUtils.getInstance().getString(KEY_SCAN_RESULT, ""); + if (TextUtils.isEmpty(cache)) { + return new ArrayList<>(); + } else { + return gson.fromJson(cache, new TypeToken>() { + }.getType()); + } + } + +} diff --git a/app/src/main/java/com/maning/gankmm/utils/ClipUtils.java b/app/src/main/java/com/maning/gankmm/utils/ClipUtils.java new file mode 100644 index 0000000..1809350 --- /dev/null +++ b/app/src/main/java/com/maning/gankmm/utils/ClipUtils.java @@ -0,0 +1,22 @@ +package com.maning.gankmm.utils; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.text.TextUtils; + +public class ClipUtils { + + public static void copy(Context context, String content){ + if(TextUtils.isEmpty(content)){ + return; + } + //获取剪贴板管理器: + ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + // 创建普通字符型ClipData + ClipData mClipData = ClipData.newPlainText("Label", content); + // 将ClipData内容放到系统剪贴板里。 + cm.setPrimaryClip(mClipData); + } + +} diff --git a/app/src/main/java/com/maning/gankmm/utils/MMKVUtils.java b/app/src/main/java/com/maning/gankmm/utils/MMKVUtils.java new file mode 100644 index 0000000..7268d52 --- /dev/null +++ b/app/src/main/java/com/maning/gankmm/utils/MMKVUtils.java @@ -0,0 +1,77 @@ +package com.maning.gankmm.utils; + +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.tencent.mmkv.MMKV; + +/** + * @author : maning + * @date : 2020-10-16 + * @desc : + */ +public class MMKVUtils { + + private static final String TIME_FLAG = "--&T&--"; + private static MMKV defaultMMKV; + + public static MMKV getInstance() { + if (defaultMMKV == null) { + defaultMMKV = MMKV.defaultMMKV(); + } + return defaultMMKV; + } + + public static T getObject(String key, Class classOfT) { + String result = getInstance().decodeString(key); + if (TextUtils.isEmpty(result)) { + return null; + } + return new Gson().fromJson(result, classOfT); + } + + public static boolean saveObject(String key, String value) { + return getInstance().encode(key, value); + } + + /** + * 保存数据 + * + * @param key key + * @param value value + * @param saveTime 保存时间长度,秒 + */ + public static void saveWithTime(String key, String value, int saveTime) { + //创建带有时间标记的value+保存到的时间 + value = value + TIME_FLAG + (System.currentTimeMillis() / 1000 + saveTime); + getInstance().encode(key, value); + } + + public static String getWithTime(String key) { + String result = getInstance().decodeString(key); + if (TextUtils.isEmpty(result)) { + return ""; + } + if (result.contains(TIME_FLAG)) { + String[] split = result.split(TIME_FLAG); + if (split.length > 1) { + String time = split[1]; + String value = split[0]; + if (!TextUtils.isEmpty(time)) { + long current = System.currentTimeMillis() / 1000; + long saveTime = Long.parseLong(time); + if (current > saveTime) { + //过期 + getInstance().removeValueForKey(key); + result = ""; + } else { + result = value; + } + } + } + } + return result; + } + + +} diff --git a/app/src/main/java/com/maning/gankmm/utils/ThreadPoolUtils.java b/app/src/main/java/com/maning/gankmm/utils/ThreadPoolUtils.java new file mode 100644 index 0000000..8028701 --- /dev/null +++ b/app/src/main/java/com/maning/gankmm/utils/ThreadPoolUtils.java @@ -0,0 +1,70 @@ +package com.maning.gankmm.utils; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.FutureTask; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author : maning + * @desc : 线程池工具类 + */ +public class ThreadPoolUtils { + + /** + * 线程池核心线程数 + */ + private static int CORE_POOL_SIZE = 0; + /** + * 线程池最大线程数 + */ + private static int MAX_POOL_SIZE = 128; + /** + * 额外线程空状态生存时间 + */ + private static int KEEP_ALIVE_TIME = 60; + /** + * 阻塞队列。当核心线程都被占用,且阻塞队列已满的情况下,才会开启额外线程。 + */ + private static BlockingQueue workQueue = new ArrayBlockingQueue(100); + /** + * 线程池 + */ + private static ThreadPoolExecutor threadPool; + + private ThreadPoolUtils() { + } + + /** + * 线程工厂 + */ + private static ThreadFactory threadFactory = new ThreadFactory() { + private final AtomicInteger integer = new AtomicInteger(); + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "ThreadPoolUtils thread:" + integer.getAndIncrement()); + } + }; + + static { + threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, + TimeUnit.SECONDS, workQueue, threadFactory); + } + + public static void execute(Runnable runnable) { + threadPool.execute(runnable); + } + + public static void execute(FutureTask futureTask) { + threadPool.execute(futureTask); + } + + public static void cancel(FutureTask futureTask) { + futureTask.cancel(true); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/maning/gankmm/utils/UserUtils.java b/app/src/main/java/com/maning/gankmm/utils/UserUtils.java index eba1c97..93ba790 100644 --- a/app/src/main/java/com/maning/gankmm/utils/UserUtils.java +++ b/app/src/main/java/com/maning/gankmm/utils/UserUtils.java @@ -1,48 +1,25 @@ package com.maning.gankmm.utils; -import com.maning.gankmm.app.MyApplication; -import com.maning.gankmm.bean.mob.CitysEntity; import com.maning.gankmm.bean.mob.MobUserInfo; /** - * Created by maning on 2017/4/1. + * @author : maning + * @date : 2020-10-16 + * @desc : */ - public class UserUtils { - private static final String cache_citys = "Cache_Citys"; - private static final String cache_UserLogin = "cache_UserLogin"; - - public static void saveCitysCache(CitysEntity citysEntity) { - if (citysEntity != null) { - MyApplication.getACache().put(cache_citys, citysEntity); - } - } - - public static CitysEntity getCitysCache() { - CitysEntity citysEntity = (CitysEntity) MyApplication.getACache().getAsObject(cache_citys); - return citysEntity; - } - //退出登录 public static void quitLogin() { - MyApplication.getACache().put(cache_UserLogin, new MobUserInfo()); } //用户登录信息 public static void saveUserCache(MobUserInfo userInfo) { - if (userInfo != null) { - MyApplication.getACache().put(cache_UserLogin, userInfo); - } } //获取用户信息 public static MobUserInfo getUserCache() { - MobUserInfo userInfo = (MobUserInfo) MyApplication.getACache().getAsObject(cache_UserLogin); - if(userInfo == null){ - userInfo = new MobUserInfo(); - } - return userInfo; + return null; } } diff --git a/app/src/main/java/com/maning/gankmm/utils/ZxingScanUtils.java b/app/src/main/java/com/maning/gankmm/utils/ZxingScanUtils.java new file mode 100644 index 0000000..30a1968 --- /dev/null +++ b/app/src/main/java/com/maning/gankmm/utils/ZxingScanUtils.java @@ -0,0 +1,66 @@ +package com.maning.gankmm.utils; + +import android.app.Activity; +import android.content.Intent; + +import com.google.zxing.client.android.MNScanManager; +import com.google.zxing.client.android.model.MNScanConfig; +import com.google.zxing.client.android.other.MNScanCallback; +import com.maning.gankmm.ui.activity.tools.ScanResultActivity; + +/** + * @author : maning + * @date : 2020-10-16 + * @desc : + */ +public class ZxingScanUtils { + + private static final String COLOR_MAIN = "#62e203"; + + public static void open(final Activity activity) { + //自定义扫描 + MNScanConfig scanConfig = new MNScanConfig.Builder() + //设置完成震动 + .isShowVibrate(false) + //扫描完成声音 + .isShowBeep(true) + //显示相册功能 + .isShowPhotoAlbum(true) + //显示闪光灯 + .isShowLightController(true) + //自定义文案 + .setScanHintText("请对准二维码/条形码识别") + //扫描线的颜色 + .setScanColor(COLOR_MAIN) + //是否显示缩放控制器 + .isShowZoomController(false) + //扫描线样式 + .setLaserStyle(MNScanConfig.LaserStyle.Line) + //是否全屏范围扫描 + .setFullScreenScan(true) + //二维码标记点 + .isShowResultPoint(true) + .setResultPointConfigs(40, 30, 10, "#70FFFFFF", "#7000A81F") + .builder(); + MNScanManager.startScan(activity, scanConfig, new MNScanCallback() { + @Override + public void onActivityResult(int resultCode, Intent data) { + switch (resultCode) { + case MNScanManager.RESULT_SUCCESS: + String resultSuccess = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS); + //扫描成功 + //跳转到扫码结果页面 + ScanResultActivity.open(activity, resultSuccess); + break; + case MNScanManager.RESULT_FAIL: + String resultError = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR); + MyToast.showShortToast(resultError); + break; + case MNScanManager.RESULT_CANCLE: + break; + } + } + }); + } + +} diff --git a/app/src/main/res/drawable/gank_icon_tools_scan.xml b/app/src/main/res/drawable/gank_icon_tools_scan.xml new file mode 100644 index 0000000..da4aaf1 --- /dev/null +++ b/app/src/main/res/drawable/gank_icon_tools_scan.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/gank_icon_tools_scancode.xml b/app/src/main/res/drawable/gank_icon_tools_scancode.xml new file mode 100644 index 0000000..a663891 --- /dev/null +++ b/app/src/main/res/drawable/gank_icon_tools_scancode.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/app/src/main/res/layout/activity_scan_result.xml b/app/src/main/res/layout/activity_scan_result.xml new file mode 100644 index 0000000..cad2d55 --- /dev/null +++ b/app/src/main/res/layout/activity_scan_result.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + +