diff --git a/README.md b/README.md
index 27d41d4..9030026 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
### 项目简介
“优聚”是一款集多个平台的资讯内容、复合型优秀资源和实用功能的APP,打破传统限制,融合多元,发现更多、更优秀、更有趣的东西。后续也会加入更多新的功能。也欢迎各位提出意见。
-项目是一款组件化综合案例,包含新闻,MONO资讯,开眼视频,美女图片,垃圾分类,一言,古诗词,智能聊天机器人,语音识别功能,干货集中营,豆瓣电影等等模块。
+项目是一款组件化综合案例,包含新闻,MONO资讯,开眼视频,知乎日报,美女图片,垃圾分类,一言,古诗词,智能聊天机器人,语音识别功能,干货集中营,豆瓣电影等等模块。
项目利用业余时间开发,时间不固定,暂时只实现了这些功能。
### 主要模块
diff --git a/base/src/main/java/com/heyongrui/base/assist/ConfigConstants.java b/base/src/main/java/com/heyongrui/base/assist/ConfigConstants.java
index 7772ddc..2ec4cc6 100644
--- a/base/src/main/java/com/heyongrui/base/assist/ConfigConstants.java
+++ b/base/src/main/java/com/heyongrui/base/assist/ConfigConstants.java
@@ -39,6 +39,7 @@ public class ConfigConstants {
public static final String PATH_KAIYAN_LIST = "/module/kaiyanList";
public static final String PATH_KAIYAN_DETAIL = "/module/kaiyanDetail";
public static final String PATH_DOUBAN = "/module/douban";
+ public static final String PATH_ZHIHU_DAILY_NEWS = "/module/zhiHuDailyNews";
public static final String PATH_GARBAGE_CLASSIFY = "/module/garbageClassify";
public static final String PATH_H5 = "/module/h5";
public static final String PATH_MODULE_PROVIDER = "/module/main/service";
diff --git a/base/src/main/java/com/heyongrui/base/utils/FileUtil.java b/base/src/main/java/com/heyongrui/base/utils/FileUtil.java
index 59697fa..eb6a657 100644
--- a/base/src/main/java/com/heyongrui/base/utils/FileUtil.java
+++ b/base/src/main/java/com/heyongrui/base/utils/FileUtil.java
@@ -1,11 +1,19 @@
package com.heyongrui.base.utils;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
+import android.webkit.MimeTypeMap;
+
+import androidx.core.content.FileProvider;
+
+import com.blankj.utilcode.util.ToastUtils;
+import com.heyongrui.base.R;
import java.io.File;
import java.io.FileInputStream;
@@ -20,102 +28,48 @@ public class FileUtil {
public FileUtil() {
}
- public static final String[][] MIME_MapTable = {
- //{后缀名, MIME类型}
- {".3gp", "video/3gpp"},
- {".apk", "application/vnd.android.package-archive"},
- {".asf", "video/x-ms-asf"},
- {".avi", "video/x-msvideo"},
- {".bin", "application/octet-stream"},
- {".bmp", "image/bmp"},
- {".c", "text/plain"},
- {".class", "application/octet-stream"},
- {".conf", "text/plain"},
- {".cpp", "text/plain"},
- {".doc", "application/msword"},
- {".exe", "application/octet-stream"},
- {".gif", "image/gif"},
- {".gtar", "application/x-gtar"},
- {".gz", "application/x-gzip"},
- {".h", "text/plain"},
- {".htm", "text/html"},
- {".html", "text/html"},
- {".jar", "application/java-archive"},
- {".java", "text/plain"},
- {".jpeg", "image/jpeg"},
- {".jpg", "image/jpeg"},
- {".js", "application/x-javascript"},
- {".log", "text/plain"},
- {".m3u", "audio/x-mpegurl"},
- {".m4a", "audio/mp4a-latm"},
- {".m4b", "audio/mp4a-latm"},
- {".m4p", "audio/mp4a-latm"},
- {".m4u", "video/vnd.mpegurl"},
- {".m4v", "video/x-m4v"},
- {".mov", "video/quicktime"},
- {".mp2", "audio/x-mpeg"},
- {".mp3", "audio/x-mpeg"},
- {".mp4", "video/mp4"},
- {".mpc", "application/vnd.mpohun.certificate"},
- {".mpe", "video/mpeg"},
- {".mpeg", "video/mpeg"},
- {".mpg", "video/mpeg"},
- {".mpg4", "video/mp4"},
- {".mpga", "audio/mpeg"},
- {".msg", "application/vnd.ms-outlook"},
- {".ogg", "audio/ogg"},
- {".pdf", "application/pdf"},
- {".png", "image/png"},
- {".pps", "application/vnd.ms-powerpoint"},
- {".ppt", "application/vnd.ms-powerpoint"},
- {".prop", "text/plain"},
- {".rar", "application/x-rar-compressed"},
- {".rc", "text/plain"},
- {".rmvb", "audio/x-pn-realaudio"},
- {".rtf", "application/rtf"},
- {".sh", "text/plain"},
- {".tar", "application/x-tar"},
- {".tgz", "application/x-compressed"},
- {".txt", "text/plain"},
- {".wav", "audio/x-wav"},
- {".wma", "audio/x-ms-wma"},
- {".wmv", "audio/x-ms-wmv"},
- {".wps", "application/vnd.ms-works"},
- //{".xml", "text/xml"},
- {".xml", "text/plain"},
- {".z", "application/x-compress"},
- {".zip", "application/zip"},
- {"", "*/*"}
- };
public static void openFileBySystem(Context context, String filePath) {
+ if (null == context) return;
if (TextUtils.isEmpty(filePath)) return;
- Intent intent = new Intent();
- File file = new File(filePath);
- if (!file.exists()) return;
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//设置标记
- intent.setAction(Intent.ACTION_VIEW);//动作,查看
- intent.setDataAndType(Uri.fromFile(file), getMIMEType(file));//设置类型
- context.startActivity(intent);
- }
+ try {
+ Intent intent = new Intent();
+ File file = new File(filePath);
+ if (!file.exists()) return;
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//设置标记
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
+ intent.setAction(Intent.ACTION_VIEW);//动作,查看
+
+ //使用系统API,获取文件MimeType类型
+ String mimeType = null;
+ String extension = MimeTypeMap.getFileExtensionFromUrl(filePath);
+ if (!TextUtils.isEmpty(extension)) {
+ //使用系统API,获取MimeTypeMap的单例实例,然后调用其内部方法获取文件后缀名(扩展名)所对应的MIME类型
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
+ }
- public static String getMIMEType(File file) {
- String type = "*/*";
- String fName = file.getName();
- //获取后缀名前的分隔符"."在fName中的位置。
- int dotIndex = fName.lastIndexOf(".");
- if (dotIndex < 0)
- return type;
- /* 获取文件的后缀名 */
- String fileType = fName.substring(dotIndex, fName.length()).toLowerCase();
- if (fileType == null || "".equals(fileType))
- return type;
- //在MIME和文件类型的匹配表中找到对应的MIME类型。
- for (int i = 0; i < MIME_MapTable.length; i++) {
- if (fileType.equals(MIME_MapTable[i][0]))
- type = MIME_MapTable[i][1];
+ //适配不同版本Uri处理
+ Uri uri = null;
+ if (Build.VERSION.SDK_INT >= 24) {
+ uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);
+ } else {
+ uri = Uri.fromFile(file);
+ }
+ if (null != uri) {
+ intent.setDataAndType(uri, mimeType);//设置类型
+ }
+
+ //判断手机是否有打开文件的相关应用
+ ComponentName componentName = intent.resolveActivity(context.getPackageManager());
+ if (componentName != null) {
+ context.startActivity(intent);
+ } else {
+ ToastUtils.showShort(context.getString(R.string.no_app_support_tip));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ ToastUtils.showShort(context.getString(R.string.no_app_support_tip));
}
- return type;
}
public static boolean fileIsExists(String path) {
diff --git a/base/src/main/java/com/heyongrui/base/utils/TimeUtil.java b/base/src/main/java/com/heyongrui/base/utils/TimeUtil.java
index aa20d4c..3d41851 100644
--- a/base/src/main/java/com/heyongrui/base/utils/TimeUtil.java
+++ b/base/src/main/java/com/heyongrui/base/utils/TimeUtil.java
@@ -196,4 +196,22 @@ public static String getCNDate(Date date) {
cnDate.append("日");
return cnDate.toString();
}
+
+ /**
+ * 判断是否是同一天
+ */
+ public static boolean isSameDay(Date date1, Date date2) {
+ if (null == date1 || null == date2) return false;
+
+ Calendar calDateA = Calendar.getInstance();
+ calDateA.setTime(date1);
+
+ Calendar calDateB = Calendar.getInstance();
+ calDateB.setTime(date2);
+
+ return calDateA.get(Calendar.YEAR) == calDateB.get(Calendar.YEAR)
+ && calDateA.get(Calendar.MONTH) == calDateB.get(Calendar.MONTH)
+ && calDateA.get(Calendar.DAY_OF_MONTH) == calDateB
+ .get(Calendar.DAY_OF_MONTH);
+ }
}
diff --git a/base/src/main/java/com/heyongrui/base/widget/ReSpinner.java b/base/src/main/java/com/heyongrui/base/widget/ReSpinner.java
index c91ceb2..32338d1 100644
--- a/base/src/main/java/com/heyongrui/base/widget/ReSpinner.java
+++ b/base/src/main/java/com/heyongrui/base/widget/ReSpinner.java
@@ -90,11 +90,13 @@ public void onItemSelected(AdapterView> adapterView, View view, int i, long l)
onReItemSelected(adapterView, view, i, l);
} else {//初始默认不选中
if (isFirst) {
- view.setVisibility(View.INVISIBLE);
+ if (null != view) {
+ view.setVisibility(View.INVISIBLE);
+ }
isFirst = false;
onReItemSelected(adapterView, view, -1, -1);
} else {
- if (view.getVisibility() != View.VISIBLE) {
+ if (null != view && view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
onReItemSelected(adapterView, view, i, l);
diff --git a/base/src/main/res/values/strings.xml b/base/src/main/res/values/strings.xml
index c040270..7f9d2ef 100644
--- a/base/src/main/res/values/strings.xml
+++ b/base/src/main/res/values/strings.xml
@@ -30,5 +30,6 @@
清理成功
完成
没有搜索到相关内容
+ 手机暂无应用支持打开此文件
添加
diff --git a/config.gradle b/config.gradle
index 3b2c228..401712b 100644
--- a/config.gradle
+++ b/config.gradle
@@ -3,7 +3,7 @@ ext {
isRunAloneUser = false;//user模块是否可以单独运行
isRunAloneModule = false;//module模块是否可以单独运行
isRunAloneModule2 = false;//module2模块是否可以单独运行
- isRunAloneIflytek = false;//科大讯飞模块是否可以单独运行
+ isRunAloneIflytek = true;//科大讯飞模块是否可以单独运行
//版本号控制
versions = [
//Project
@@ -43,5 +43,6 @@ ext {
tagcloudlib : '1.2.0',
jiaozivideoplayer : '7.0.4',
ahbottomnavigation: '2.3.4',
+ banner : '2.3.16',
]
}
\ No newline at end of file
diff --git a/module/build.gradle b/module/build.gradle
index 45b5f74..59abc00 100644
--- a/module/build.gradle
+++ b/module/build.gradle
@@ -98,6 +98,8 @@ dependencies {
kapt "com.google.dagger:dagger-compiler:${versions.dagger}"
//视频框架
implementation "cn.jzvd:jiaozivideoplayer:${versions.jiaozivideoplayer}"
+ //banner
+ implementation "com.ms:Banner-androidx:${versions.banner}"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
diff --git a/module/src/main/AndroidManifest.xml b/module/src/main/AndroidManifest.xml
index 7f30aba..9a97aaa 100644
--- a/module/src/main/AndroidManifest.xml
+++ b/module/src/main/AndroidManifest.xml
@@ -46,5 +46,8 @@
+
diff --git a/module/src/main/debug/AndroidManifest.xml b/module/src/main/debug/AndroidManifest.xml
index 646853a..d168e02 100644
--- a/module/src/main/debug/AndroidManifest.xml
+++ b/module/src/main/debug/AndroidManifest.xml
@@ -62,6 +62,9 @@
+
diff --git a/module/src/main/java/com/heyongrui/module/ModuleFragment.java b/module/src/main/java/com/heyongrui/module/ModuleFragment.java
index 88067f5..95122e8 100644
--- a/module/src/main/java/com/heyongrui/module/ModuleFragment.java
+++ b/module/src/main/java/com/heyongrui/module/ModuleFragment.java
@@ -94,6 +94,9 @@ private void initRecyclerView(RecyclerView recyclerView) {
case 8://电影
ARouter.getInstance().build(ConfigConstants.PATH_DOUBAN).navigation();
break;
+ case 9://知乎日报
+ ARouter.getInstance().build(ConfigConstants.PATH_ZHIHU_DAILY_NEWS).navigation();
+ break;
}
});
dataList.add(new ModuleSectionEntity(ModuleSectionEntity.MENU_CARD, new MenuCardDto(getString(R.string.tea), R.drawable.ic_tea, 1)));
@@ -104,6 +107,7 @@ private void initRecyclerView(RecyclerView recyclerView) {
dataList.add(new ModuleSectionEntity(ModuleSectionEntity.MENU_CARD, new MenuCardDto(getString(R.string.kaiyan), R.drawable.ic_kaiyan, 6)));
dataList.add(new ModuleSectionEntity(ModuleSectionEntity.MENU_CARD, new MenuCardDto(getString(R.string.garbage_classification2), R.drawable.ic_ashcan, 7)));
dataList.add(new ModuleSectionEntity(ModuleSectionEntity.MENU_CARD, new MenuCardDto(getString(R.string.movie), R.drawable.ic_movie, 8)));
+ dataList.add(new ModuleSectionEntity(ModuleSectionEntity.MENU_CARD, new MenuCardDto(getString(R.string.zhihu_daily), R.drawable.ic_zhihu, 9)));
monoAdapter.replaceData(dataList);
}
}
diff --git a/module/src/main/java/com/heyongrui/module/adapter/ModuleSectionAdapter.java b/module/src/main/java/com/heyongrui/module/adapter/ModuleSectionAdapter.java
index 3716d50..981461b 100644
--- a/module/src/main/java/com/heyongrui/module/adapter/ModuleSectionAdapter.java
+++ b/module/src/main/java/com/heyongrui/module/adapter/ModuleSectionAdapter.java
@@ -53,6 +53,7 @@
import com.heyongrui.module.data.dto.PoemGroupDto;
import com.heyongrui.module.data.dto.PoemSearchDto;
import com.heyongrui.module.data.dto.TodayRecommendPoemDto;
+import com.heyongrui.module.data.dto.ZhiHuDailyNewsDto;
import com.heyongrui.module.mono.view.MonoTeaActivity;
import java.util.Calendar;
@@ -86,13 +87,19 @@ public ModuleSectionAdapter(int sectionHeadResId, List data
addItemType(ModuleSectionEntity.POEM, R.layout.recycle_item_poem);
addItemType(ModuleSectionEntity.POEM_GROUP, R.layout.recycle_item_poem_group);
addItemType(ModuleSectionEntity.DOUBAN_MOVIE, R.layout.recycle_item_douban_movie);
+ addItemType(ModuleSectionEntity.ZHIHU_NEWS, R.layout.recycle_item_zhihu_news);
}
@Override
protected void convertHead(BaseViewHolder helper, ModuleSectionEntity item) {
-// TextView tvHeadSection = helper.getView(R.id.tv_head_section);
-// tvHeadSection.setText(item.header);
-// tvHeadSection.setVisibility(item.isShow() ? View.VISIBLE : View.GONE);
+ switch (item.getItemType()) {
+ case ModuleSectionEntity.ZHIHU_NEWS:
+ TextView tvHeadSection = helper.getView(android.R.id.text1);
+ if (null != tvHeadSection) {
+ tvHeadSection.setText(TextUtils.isEmpty(item.header) ? "" : item.header);
+ }
+ break;
+ }
}
@Override
@@ -587,6 +594,24 @@ public void onItemClick(Context context, int position, RatioImageView ratioImage
tvRate.setText(rate);
}
break;
+ case ModuleSectionEntity.ZHIHU_NEWS: {
+ UiUtil.setOnclickFeedBack(mContext, ContextCompat.getColor(mContext, R.color.background), ContextCompat.getColor(mContext, R.color.gray), helper.itemView);
+ TextView tvTitle = helper.getView(R.id.tv_title);
+ ImageView ivCover = helper.getView(R.id.iv_cover);
+
+ String title = "", cover = "";
+ ZhiHuDailyNewsDto.StoryBean storyBean = item.getStoryBean();
+ if (null != storyBean) {
+ title = storyBean.getTitle();
+ List images = storyBean.getImages();
+ if (null != images && !images.isEmpty()) {
+ cover = images.get(0);
+ }
+ }
+ tvTitle.setText(TextUtils.isEmpty(title) ? "" : title);
+ GlideUtil.loadImage(mContext, cover, ivCover, ContextCompat.getDrawable(mContext, R.drawable.placeholder));
+ }
+ break;
}
}
}
diff --git a/module/src/main/java/com/heyongrui/module/adapter/ModuleSectionEntity.java b/module/src/main/java/com/heyongrui/module/adapter/ModuleSectionEntity.java
index 8be4a2f..9e0a0b8 100644
--- a/module/src/main/java/com/heyongrui/module/adapter/ModuleSectionEntity.java
+++ b/module/src/main/java/com/heyongrui/module/adapter/ModuleSectionEntity.java
@@ -13,6 +13,7 @@
import com.heyongrui.module.data.dto.PoemGroupDto;
import com.heyongrui.module.data.dto.PoemSearchDto;
import com.heyongrui.module.data.dto.TodayRecommendPoemDto;
+import com.heyongrui.module.data.dto.ZhiHuDailyNewsDto;
import java.util.List;
@@ -34,6 +35,7 @@ public class ModuleSectionEntity extends SectionMultiEntity implements MultiItem
public static final int POEM = 110;
public static final int POEM_GROUP = 111;
public static final int DOUBAN_MOVIE = 112;
+ public static final int ZHIHU_NEWS = 113;
private int itemType;
private int spanSize;
@@ -50,6 +52,7 @@ public class ModuleSectionEntity extends SectionMultiEntity implements MultiItem
private PoemGroupDto.DataBean groupPoemBean;
private PoemGroupDetailDto.DataBean groupPoemDataBean;
private DouBanDto.SubjectsBean subjectsBean;
+ private ZhiHuDailyNewsDto.StoryBean storyBean;
public ModuleSectionEntity(boolean isHeader, String header, boolean isShow) {
super(isHeader, header);
@@ -92,6 +95,8 @@ public ModuleSectionEntity(int itemType, int spanSize, Object object) {
this.groupPoemDataBean = (PoemGroupDetailDto.DataBean) object;
} else if (object instanceof DouBanDto.SubjectsBean) {
this.subjectsBean = (DouBanDto.SubjectsBean) object;
+ } else if (object instanceof ZhiHuDailyNewsDto.StoryBean) {
+ this.storyBean = (ZhiHuDailyNewsDto.StoryBean) object;
}
}
}
@@ -208,4 +213,12 @@ public DouBanDto.SubjectsBean getSubjectsBean() {
public void setSubjectsBean(DouBanDto.SubjectsBean subjectsBean) {
this.subjectsBean = subjectsBean;
}
+
+ public ZhiHuDailyNewsDto.StoryBean getStoryBean() {
+ return storyBean;
+ }
+
+ public void setStoryBean(ZhiHuDailyNewsDto.StoryBean storyBean) {
+ this.storyBean = storyBean;
+ }
}
diff --git a/module/src/main/java/com/heyongrui/module/dagger/ModuleComponent.java b/module/src/main/java/com/heyongrui/module/dagger/ModuleComponent.java
index a59c136..a2d9155 100644
--- a/module/src/main/java/com/heyongrui/module/dagger/ModuleComponent.java
+++ b/module/src/main/java/com/heyongrui/module/dagger/ModuleComponent.java
@@ -10,6 +10,7 @@
import com.heyongrui.module.douban.presenter.DouBanPresenter;
import com.heyongrui.module.douban.view.DouBanActivity;
import com.heyongrui.module.textword.view.SmartRobotActivity;
+import com.heyongrui.module.zhihu.presenter.ZhiHuDailyNewsPresenter;
import dagger.Component;
@@ -33,4 +34,6 @@ public interface ModuleComponent {
void inject(ModuleFragment moduleFragment);
void inject(SmartRobotActivity smartRobotActivity);
+
+ void inject(ZhiHuDailyNewsPresenter zhiHuDailyNewsPresenter);
}
diff --git a/module/src/main/java/com/heyongrui/module/data/api/DailyLifeApi.java b/module/src/main/java/com/heyongrui/module/data/api/DailyLifeApi.java
index 0854a87..68f0d6b 100644
--- a/module/src/main/java/com/heyongrui/module/data/api/DailyLifeApi.java
+++ b/module/src/main/java/com/heyongrui/module/data/api/DailyLifeApi.java
@@ -1,7 +1,10 @@
package com.heyongrui.module.data.api;
+import com.heyongrui.module.data.dto.ZhiHuDailyNewsDto;
+
import io.reactivex.Observable;
import retrofit2.http.GET;
+import retrofit2.http.Path;
import retrofit2.http.Query;
public interface DailyLifeApi {
@@ -11,4 +14,26 @@ public interface DailyLifeApi {
*/
@GET("api/GetRefuseClassification.php")
Observable