新增轮播图跳转web页面、轮播、推荐歌单数据存储( 简易音乐 七)
关于
本篇主要使用到了腾讯x5 浏览器webview与litepal操作sqlite存储数据至本地。上一篇新增我的推荐歌单、通过ViewPager2+RadioGroup重构主界面( 简易音乐 六)
效果图
这里表面腾讯x5内核加载成功
gif图片提示违规了,可能是涉及版权之类的吧,效果可参考网易云的轮播图打开的网页链接的效果。
第一步,添加引用
添加litepal引用:
//sqlite数据库
implementation 'org.litepal.guolindev:core:3.2.3'
去官网下载页面,下载sdk,然后将里面的jar包,复制到我们的项目的lib中,右键选择Add As Library然后会自动在buil中添加如下一行:
implementation files('libs/tbs_sdk_thirdapp_v4.3.0.93_43993_sharewithdownloadwithfile_withoutGame_obfs_20210220_114728.jar')
如果添加失败,在build内加上这句:
android{
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
......
}
在application中初始化:
// 在调用TBS初始化、创建WebView之前进行如下配置
HashMap map = new HashMap();
map.put(TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER, true);
map.put(TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE, true);
QbSdk.setDownloadWithoutWifi(true);
QbSdk.initTbsSettings(map);
QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
@Override
public void onViewInitFinished(boolean arg0) {
// TODO Auto-generated method stub
//x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
Log.e("app", " onViewInitFinished is " + arg0);
}
@Override
public void onCoreInitFinished() {
// TODO Auto-generated method stub
}
};
//x5内核初始化接口
QbSdk.initX5Environment(getApplicationContext(), cb);
//litepal初始化
LitePal.initialize(instance);
在AndroidManifest.xml下配置x5下载服务:
<service
android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
android:label="dexopt"
android:process=":dexopt" />
第一次加载x5内核(wifi下会消耗部分时间),可以在android studio的logcat中看到下载进度,然后会有app: onViewInitFinished is true
的提示,表示内核加载成功。
新增数据库实体类
新增BannerSQ.class
与RecommendSQ.class
实体类如下:
public class BannerSQ extends LitePalSupport {
@Column(unique = true,defaultValue = "unKnow")
private String idName;
private String pic;
private String titleColor;
private String typeTitle;
private String url;
private Object song;
public Object getSong() {
return song;
}
public void setSong(Object song) {
this.song = song;
}
public void setPic(String pic) {
this.pic = pic;
}
public void setTitleColor(String titleColor) {
this.titleColor = titleColor;
}
public void setTypeTitle(String typeTitle) {
this.typeTitle = typeTitle;
}
public void setUrl(String url) {
this.url = url;
}
public String getPic() {
return pic;
}
public String getIdName() {
return idName;
}
public void setIdName(String idName) {
this.idName = idName;
}
public String getTitleColor() {
return titleColor;
}
public String getTypeTitle() {
return typeTitle;
}
public String getUrl() {
return url;
}
}
public class RecommendSQ extends LitePalSupport {
private String picUrl;
private long playcount;
private String name;
public String getPicUrl() {
return picUrl;
}
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
public long getPlaycount() {
return playcount;
}
public void setPlaycount(long playcount) {
this.playcount = playcount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在src/main/下新增一个assets文件夹,并新增文件litepal/xml,写法格式固定:
<?xml version="1.0" encoding="UTF-8" ?>
<litepal>
<dbname value="musicHome" ></dbname>
<!--没修过一次或是新增数据库实体类这里都要+1-->
<version value="7"></version>
<list>
<mapping class="com.tobey.jianyimusic.data.database.BannerSQ"/>
<mapping class="com.tobey.jianyimusic.data.database.RecommendSQ"/>
</list>
</litepal>
修改fragment代码
修改轮播图、推荐歌单的存储类,新增跳转web页面
public class Fragment_main extends BaseFragment {
@BindView(R.id.banner)
Banner banner;
@BindView(R.id.text_fm)
TextView textView_fm;
@BindView(R.id.recommend_recycle)
RecyclerView recyclerRecommend;
//修改为数据库实体类,方便数据库存储
List<BannerSQ> list_banner_sq;
List<RecommendSQ> list_recommend_sq;
private static int potsition = 0;
//适配器也要修改,将RecommendListBean替换成RecommendSQ
private RecommdListAdapter adapter;
@Override
protected int getLayout() {
return R.layout.fragment_main;
}
@Override
protected void initView(View view) {
String date = Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + "";
textView_fm.setText(date);
initData();
}
private void initData() {
RetrofitUtils.getmApi().getBanner(1)
.compose(RXHelper.observableIO2Main(getContext()))
.subscribe(new StaticMethodUtils.OnCallback<banner_bean>(){
@Override
public void onNext(banner_bean banner_bean) {
if (banner_bean.getCode() == 200){
updateBanner(banner_bean.getBanners());
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
//网络异常则查询数据库来充当banner轮播图数据
queryDb();
}
});
LinearLayoutManager manager = new LinearLayoutManager(getContext());
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerRecommend.setLayoutManager(manager);
RetrofitUtils.getmApi().getRecommendPlayList()
.compose(RXHelper.observableIO2Main(getContext()))
.subscribe(new StaticMethodUtils.OnCallback<RecommendListBean>(){
@Override
public void onNext(RecommendListBean recommendListBean) {
if (recommendListBean.getCode() == 200){
list_recommend_sq = new ArrayList<>();
int size = recommendListBean.getRecommend().size();
for (int i=0;i<size;i++){
RecommendSQ recommendSQ = new RecommendSQ();
recommendSQ.setName(recommendListBean.getRecommend().get(i).getName());
recommendSQ.setPicUrl(recommendListBean.getRecommend().get(i).getPicUrl());
recommendSQ.setPlaycount(recommendListBean.getRecommend().get(i).getPlaycount());
list_recommend_sq.add(recommendSQ);
}
adapter = new RecommdListAdapter(list_recommend_sq);
adapter.notifyDataSetChanged();
recyclerRecommend.setAdapter(adapter);
//sqlite在使用前要调用LitePal.getDatabase();建议数据库表,但是我们待会会修改SplashActivity.java,所以此处不用添加
//通过这个方法可以判断数据是否存储成功
boolean result = LitePal.saveAll(list_recommend_sq);
if (!result){
Log.e("数据库内容","数据收藏存储失败");
}
}
}
@Override
public void onError(Throwable e) {
super.onError(e);
//查询推荐歌单数据库表
queryRecommendDb();
}
});
}
private void queryRecommendDb() {
//查询RecommendSQ表中第一条数据是否存在用于判空
if (LitePal.findFirst(RecommendSQ.class) != null){
list_recommend_sq = LitePal.findAll(RecommendSQ.class);
adapter = new RecommdListAdapter(list_recommend_sq);
adapter.notifyDataSetChanged();
recyclerRecommend.setAdapter(adapter);
}
}
private void queryDb() {
if (LitePal.findFirst(BannerSQ.class) != null){
list_banner_sq = LitePal.findAll(BannerSQ.class);
int s = list_banner_sq.size();
banner.setIndicator(new RectangleIndicator(getActivity()))
.setIndicatorHeight(5)
.setIndicatorWidth(6,6)
.setIndicatorGravity(IndicatorConfig.Direction.CENTER)
.setAdapter(new ImageTitleAdapter(list_banner_sq,this))
.addBannerLifecycleObserver(getActivity())//添加生命周期观察者
.setIntercept(true)
.setOnBannerListener(new OnBannerListener() {
@Override
public void OnBannerClick(Object data, int position) {
}
})
.setBannerRound(10f);
}
}
private void updateBanner(List<banner_bean.BannersBean> banners) {
if (banners !=null && banners.size() >0){
int i = banners.size();
list_banner_sq = new ArrayList<>();
for (int j=0;j<i;j++){
BannerSQ bannerSQ = new BannerSQ();
bannerSQ.setPic(banners.get(j).getPic());
bannerSQ.setTitleColor(banners.get(j).getTitleColor());
bannerSQ.setUrl(banners.get(j).getUrl());
bannerSQ.setTypeTitle(banners.get(j).getTypeTitle());
bannerSQ.setIdName(j+1+"");
bannerSQ.setSong(banners.get(j).getSong());
list_banner_sq.add(bannerSQ);
}
banner.setIndicator(new RectangleIndicator(getActivity()))
.setIndicatorHeight(5)
.setIndicatorWidth(6,6)
.setIndicatorGravity(IndicatorConfig.Direction.CENTER)
.setAdapter(new ImageTitleAdapter(list_banner_sq,this))
.addBannerLifecycleObserver(getActivity())//添加生命周期观察者
.setIntercept(true)
.setOnBannerListener(new OnBannerListener() {
@Override
public void OnBannerClick(Object data, int position) {
//只有url不为空才表示有web网页可以加载
if (list_banner_sq.get(position).getUrl() !=null){
ARouter.getInstance()
.build(Config.ROUTE_WEB)
.withString("url",list_banner_sq.get(position).getUrl())
.navigation(getActivity());
}
}
})
.setBannerRound(10f);
insertBannerDb();
}
}
private void insertBannerDb() {
boolean result = LitePal.saveAll(list_banner_sq);
if (result){
Log.e("数据库内容","数据存储成功");
// ToastUtils.show("数据存储成功");
}else {
Log.e("数据库内容","数据存储失败");
// ToastUtils.show("数据存储失败");
}
}
@Override
protected void setListener() {
}
@Override
public void onDestroy() {
super.onDestroy();
if (list_banner_sq !=null){
list_banner_sq.clear();
list_banner_sq = null;
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (list_recommend_sq !=null){
list_recommend_sq.clear();
list_recommend_sq = null;
}
}
}
修改config.java,添加WebActivity的标签:
String ROUTE_WEB = "/app/web";
修改SplashActivity.java
,在初始化的地方添加如下判断方法,用于数据库清理,因为litepal暂时未做list数据的判重更新操作,之后插入,所以我在启动动画页面对数据库在有网络情况下进行数据删除。
//建立数据库
LitePal.getDatabase();
if (LitePal.findFirst(BannerSQ.class) != null&& StaticMethodUtils.isNetWorkActive(SplashActivity.this)){
LitePal.deleteAll(BannerSQ.class);
LitePal.deleteAll(RecommendSQ.class);
Log.e("数据库内容","删除功能");
}
新增WebActivity页面加载网页
webview布局页面如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".home.WebActivity">
<include layout="@layout/common_title" android:id="@+id/title"/>
<com.tencent.smtt.sdk.WebView
android:id="@+id/web"
android:layout_below="@+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="3dip"
android:layout_below="@+id/title"
android:progressDrawable="@drawable/pg"
/>
</RelativeLayout>
设置ProgressBar的透明背景pg.xml,使网页加载完成展示的不会突兀:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@android:id/background">
<shape>
<corners android:radius="2dp" />
<gradient
android:angle="270"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"
android:startColor="@android:color/transparent" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="2dp" />
<gradient
android:centerColor="#1C66B6"
android:endColor="#1C66B6"
android:startColor="#1C66B6" />
</shape>
</clip>
</item>
</layer-list>
修改WebActivity.java
:
@Route(path = Config.ROUTE_WEB)
public class WebActivity extends BaseActivity {
@BindView(R.id.web)
WebView webView;
@BindView(R.id.progressBar)
ProgressBar pg;
@Autowired(name = "url")
String url;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
}
@Override
protected BasePresenter onCreatePresenter() {
return null;
}
@Override
protected void initData() {
Log.e("网址",url);
webView.loadUrl(url);
webView.getSettings().setGeolocationEnabled(false);//定位
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
savaData(webView);
if (webView.getX5WebViewExtension() !=null){
webView.getX5WebViewExtension().setVerticalScrollBarEnabled(false);
Log.e("内部",webView.getX5WebViewExtension().toString());
Log.e("内核版本", QbSdk.getTbsVersion(this)+"");
webView.getSettingsExtension().setDisplayCutoutEnable(true); //适配刘海屏
}
webView.setWebViewClient(client);
webView.setWebChromeClient(webChromeClient);
Log.e("当前",webView.getSettings().getUserAgentString());
}
private void savaData(WebView webView) {
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setAppCacheEnabled(true);
String appCach = getApplicationContext().getCacheDir().getAbsolutePath();
webView.getSettings().setAppCachePath(appCach);
}
WebViewClient client = new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String s) {
//拦截url调整系统浏览器
webView.loadUrl(s);
return true;
}
};
WebChromeClient webChromeClient = new WebChromeClient(){
@Override
public void onProgressChanged(WebView webView, int i) {
super.onProgressChanged(webView, i);
pg.setProgress(i);
if (i == 100){
pg.setVisibility(View.GONE);
}
}
@Override
public void onReceivedTitle(WebView webView, String s) {
super.onReceivedTitle(webView, s);
Log.e("标题",s);
/*MarqueeTextView textView = findViewById(R.id.tv_title);
textView.setUrl(s,textView);
textView.setScrollMode(SCROLL_FOREVER);
textView.setVisibility(View.VISIBLE);*/
//这里是设置标题的
setTitleText(s);
}
};
@Override
protected void initModule() {
//获取传值的地方需要绑定
ARouter.getInstance().inject(this);
//页面返回功能
setBackBtn();
}
@Override
protected void onResume() {
super.onResume();
webView.onResume();
}
@Override
protected void onPause() {
super.onPause();
webView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (webView != null){
webView.clearHistory();
webView.loadUrl("about:blank");
webView.stopLoading();
webView.setWebViewClient(null);
webView.destroy();
webView = null;
}
}
}
好了,本篇到此结束了,有问题欢迎批评指正!,觉得不错的也请点个赞奥