parent
96f8998920
commit
dfbd75e655
|
@ -2,7 +2,7 @@
|
||||||
<litepal>
|
<litepal>
|
||||||
<dbname value="book" ></dbname>
|
<dbname value="book" ></dbname>
|
||||||
|
|
||||||
<version value="9" ></version>
|
<version value="11" ></version>
|
||||||
|
|
||||||
<list>
|
<list>
|
||||||
<mapping class="com.novelbook.android.db.Chapter"></mapping>
|
<mapping class="com.novelbook.android.db.Chapter"></mapping>
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.novelbook.android.Fragments;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -68,7 +69,7 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc
|
||||||
boolean isFirstLoad = true;
|
boolean isFirstLoad = true;
|
||||||
@Override
|
@Override
|
||||||
protected void fillData() {
|
protected void fillData() {
|
||||||
catalogueList.clear();
|
|
||||||
catalogueList.addAll(pageFactory.getChapters());
|
catalogueList.addAll(pageFactory.getChapters());
|
||||||
|
|
||||||
// int currentChp =pageFactory.getCurrentChapter()-1;
|
// int currentChp =pageFactory.getCurrentChapter()-1;
|
||||||
|
@ -78,10 +79,8 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc
|
||||||
currentChp = catalogueList.size() -currentChp-1;
|
currentChp = catalogueList.size() -currentChp-1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catalogueAdapter.setData(catalogueList);
|
||||||
catalogueAdapter = new CatalogueAdapter(getContext(), catalogueList);
|
|
||||||
catalogueAdapter.setCharter(currentChp+1);
|
catalogueAdapter.setCharter(currentChp+1);
|
||||||
lv_catalogue.setAdapter(catalogueAdapter);
|
|
||||||
catalogueAdapter.setCahedChapters(catalogCached);
|
catalogueAdapter.setCahedChapters(catalogCached);
|
||||||
catalogueAdapter.notifyDataSetChanged();
|
catalogueAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
@ -103,6 +102,7 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc
|
||||||
|
|
||||||
@OnClick(R.id.btnRefresh)
|
@OnClick(R.id.btnRefresh)
|
||||||
void refresh(View view) {
|
void refresh(View view) {
|
||||||
|
pageFactory.refreshCate();
|
||||||
loadData();
|
loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +144,10 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc
|
||||||
public void loadData(){
|
public void loadData(){
|
||||||
showProgressDialog(false,"请稍等");
|
showProgressDialog(false,"请稍等");
|
||||||
|
|
||||||
|
catalogueList.clear();
|
||||||
|
catalogueAdapter = new CatalogueAdapter(getContext(), catalogueList);
|
||||||
|
|
||||||
|
lv_catalogue.setAdapter(catalogueAdapter);
|
||||||
Log.d(TAG, String .format("prepare book: start to open book cate of %s" , pageFactory.getNovle().getName()));
|
Log.d(TAG, String .format("prepare book: start to open book cate of %s" , pageFactory.getNovle().getName()));
|
||||||
|
|
||||||
new Thread() {
|
new Thread() {
|
||||||
|
@ -219,9 +223,23 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc
|
||||||
protected void initViews() {
|
protected void initViews() {
|
||||||
lv_catalogue.setFastScrollEnabled(true);
|
lv_catalogue.setFastScrollEnabled(true);
|
||||||
((MarkActivity) getActivity()).setSortcat(this);
|
((MarkActivity) getActivity()).setSortcat(this);
|
||||||
|
|
||||||
//lv_catalogue.setFastScrollStyle(R.style.FastScrollTheme); //不起作用
|
//lv_catalogue.setFastScrollStyle(R.style.FastScrollTheme); //不起作用
|
||||||
}
|
}
|
||||||
|
void initSwipeRefreshLayout(){
|
||||||
|
super.initSwipeRefreshLayout();
|
||||||
|
mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||||
|
@Override
|
||||||
|
public void onRefresh() {
|
||||||
|
|
||||||
|
// 开始刷新,设置当前为刷新状态
|
||||||
|
//swipeRefreshLayout.setRefreshing(true);
|
||||||
|
isAsc =true;
|
||||||
|
refresh(btnRefresh);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public void setFTag() {
|
public void setFTag() {
|
||||||
|
|
||||||
|
|
|
@ -620,13 +620,15 @@ public class ReadActivity extends Activity_base implements SpeechSynthesizerLis
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
else if (id == R.id.action_change_source) {
|
else if (id == R.id.action_change_source) {
|
||||||
if( pageFactory.getChapters().size()>0) {
|
// if( pageFactory.getChapters().size()>0) {
|
||||||
Intent intent = new Intent(ReadActivity.this, Activity_ChgSource.class);
|
Intent intent = new Intent(ReadActivity.this, Activity_ChgSource.class);
|
||||||
intent.putExtra(Activity_ChgSource.EXTR_ID, pageFactory.getCurrentChapter());
|
intent.putExtra(Activity_ChgSource.EXTR_ID, pageFactory.getCurrentChapter());
|
||||||
intent.putExtra(Activity_ChgSource.EXTR_TITLE, pageFactory.getChapterName());
|
intent.putExtra(Activity_ChgSource.EXTR_TITLE, pageFactory.getChapterName());
|
||||||
intent.putExtra(Activity_ChgSource.EXTR_SITE, pageFactory.getSite());
|
intent.putExtra(Activity_ChgSource.EXTR_SITE, pageFactory.getSite());
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
// }else{
|
||||||
|
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
|
|
|
@ -50,6 +50,9 @@ public class CatalogueAdapter extends BaseAdapter {
|
||||||
public void setCharter(int charter){
|
public void setCharter(int charter){
|
||||||
currentCharter = charter;
|
currentCharter = charter;
|
||||||
}
|
}
|
||||||
|
public void setData(List<Chapter> bookCatalogueList){
|
||||||
|
this.bookCatalogueList = bookCatalogueList;
|
||||||
|
}
|
||||||
|
|
||||||
public void setCahedChapters(List<Integer> listCached ){
|
public void setCahedChapters(List<Integer> listCached ){
|
||||||
bookCatalogueListCached =listCached;
|
bookCatalogueListCached =listCached;
|
||||||
|
|
|
@ -13,6 +13,7 @@ public class SiteRule extends LitePalSupport {
|
||||||
private String name;
|
private String name;
|
||||||
@Column(unique = true, nullable = false)
|
@Column(unique = true, nullable = false)
|
||||||
private String domain;
|
private String domain;
|
||||||
|
private String encoding;
|
||||||
// private String chapterUrlRegexOnMulu;
|
// private String chapterUrlRegexOnMulu;
|
||||||
private RegexOnMulu[] chapterUrlRegexOnMulu;
|
private RegexOnMulu[] chapterUrlRegexOnMulu;
|
||||||
private String chapterContentDumpRegex;
|
private String chapterContentDumpRegex;
|
||||||
|
@ -30,6 +31,14 @@ public class SiteRule extends LitePalSupport {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEncoding() {
|
||||||
|
return encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEncoding(String encoding) {
|
||||||
|
this.encoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
public String getChapterContentRegex() {
|
public String getChapterContentRegex() {
|
||||||
return chapterContentRegex;
|
return chapterContentRegex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
package com.novelbook.android.netutils;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import okhttp3.internal.http.RealResponseBody;
|
||||||
|
|
||||||
|
public class EncodingInterceptor implements Interceptor {
|
||||||
|
private final static String TAG= EncodingInterceptor.class.getSimpleName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义编码
|
||||||
|
*/
|
||||||
|
private String encoding;
|
||||||
|
|
||||||
|
public EncodingInterceptor(String encoding) {
|
||||||
|
this.encoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
|
||||||
|
Request request = chain.request();
|
||||||
|
long start = System.nanoTime();
|
||||||
|
Log.d(TAG, String.format("EncodingInterceptor Sending request: %s, headers:%s ", request.url(), request.headers()));
|
||||||
|
Response response = chain.proceed(request);
|
||||||
|
long end = System.nanoTime();
|
||||||
|
Log.d(TAG,String.format("EncodingInterceptor Received response for %s in %.1fms%n %s", response.request().url(), (end - start) / 1e6d, response.headers()) );
|
||||||
|
|
||||||
|
|
||||||
|
String contentType = response.header("Content-Type");
|
||||||
|
if (!TextUtils.isEmpty(contentType) && contentType.contains("charset")) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add header
|
||||||
|
response.newBuilder()
|
||||||
|
.removeHeader("Pragma")
|
||||||
|
.header("Content-Type", (!TextUtils.isEmpty(contentType) ? contentType + "; ":"" ) + "charset=" + encoding)
|
||||||
|
.build();
|
||||||
|
//body charset
|
||||||
|
/* String contentTypeString = response.body().contentType().charset().name() ;
|
||||||
|
if (!TextUtils.isEmpty(contentTypeString) && contentTypeString.contains("charset")) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
contentTypeString = (!TextUtils.isEmpty(contentTypeString) ? contentTypeString + "; ":"" ) + "charset=" + encoding;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
settingClientCustomEncoding(response);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setting client custom encoding when server not return encoding
|
||||||
|
* @param response
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void settingClientCustomEncoding(Response response) throws IOException {
|
||||||
|
// setHeaderContentType(response);
|
||||||
|
setBodyContentType(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set contentType in headers
|
||||||
|
* @param response
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void setHeaderContentType(Response response) throws IOException {
|
||||||
|
String contentType = response.header("Content-Type");
|
||||||
|
if (!TextUtils.isEmpty(contentType) && contentType.contains("charset")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build new headers
|
||||||
|
Headers headers = response.headers();
|
||||||
|
Headers.Builder builder = headers.newBuilder();
|
||||||
|
builder.removeAll("Content-Type");
|
||||||
|
builder.add("Content-Type", (!TextUtils.isEmpty(contentType) ? contentType + "; ":"" ) + "charset=" + encoding);
|
||||||
|
headers = builder.build();
|
||||||
|
// setting headers using reflect
|
||||||
|
Class _response = Response.class;
|
||||||
|
try {
|
||||||
|
Field field = _response.getDeclaredField("headers");
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(response, headers);
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
throw new IOException("use reflect to setting header occurred an error", e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IOException("use reflect to setting header occurred an error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set body contentType
|
||||||
|
* @param response
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void setBodyContentType(Response response) throws IOException {
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
// setting body contentTypeString using reflect
|
||||||
|
Class tmp = RealResponseBody.class;
|
||||||
|
if( !(body instanceof RealResponseBody)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Class<? extends ResponseBody> aClass = body.getClass();
|
||||||
|
try {
|
||||||
|
Field field = aClass.getDeclaredField("contentTypeString");
|
||||||
|
field.setAccessible(true);
|
||||||
|
/* Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||||
|
modifiersField.setAccessible(true);
|
||||||
|
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);*/
|
||||||
|
String contentTypeString = String.valueOf(field.get(body));
|
||||||
|
if (!TextUtils.isEmpty(contentTypeString) && contentTypeString.contains("charset")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
field.set(body, (!TextUtils.isEmpty(contentTypeString) ? contentTypeString + "; ":"" ) + "charset=" + encoding);
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
throw new IOException("use reflect to setting header occurred an error", e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IOException("use reflect to setting header occurred an error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -150,7 +150,7 @@ public class HttpMethods {
|
||||||
*/
|
*/
|
||||||
Request.Builder requestBuilder = originalRequest.newBuilder()
|
Request.Builder requestBuilder = originalRequest.newBuilder()
|
||||||
// .addHeader("Accept-Encoding", "gzip")
|
// .addHeader("Accept-Encoding", "gzip")
|
||||||
.addHeader("Accept-Encoding", Locale.getDefault().toString() )
|
// .addHeader("Accept-Encoding", Locale.getDefault().toString() )
|
||||||
// .addHeader("Accept", "application/json")
|
// .addHeader("Accept", "application/json")
|
||||||
// .addHeader("Content-Type", "application/json; charset=utf-8")
|
// .addHeader("Content-Type", "application/json; charset=utf-8")
|
||||||
// .addHeader("Device", "Android")
|
// .addHeader("Device", "Android")
|
||||||
|
@ -178,6 +178,11 @@ public class HttpMethods {
|
||||||
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||||
//设置 Debug Log 模式
|
//设置 Debug Log 模式
|
||||||
okHttpBuilder.addInterceptor(loggingInterceptor);
|
okHttpBuilder.addInterceptor(loggingInterceptor);
|
||||||
|
|
||||||
|
//设置编码
|
||||||
|
// EncodingInterceptor encodingInterceptor = new EncodingInterceptor("gbk");
|
||||||
|
// okHttpBuilder.addInterceptor(encodingInterceptor);
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -163,7 +163,7 @@ public class OnSuccessAndFaultSub extends DisposableObserver<ResponseBody>
|
||||||
} catch (Exception e2) {
|
} catch (Exception e2) {
|
||||||
Log.e(TAG, "prepare book onError: ",e );
|
Log.e(TAG, "prepare book onError: ",e );
|
||||||
} finally {
|
} finally {
|
||||||
Log.e("OnSuccessAndFaultSub", "error:" + e.getMessage());
|
Log.e("OnSuccessAndFaultSub", "error:" + e);
|
||||||
// mOnSuccessAndFaultListener.onFault("error:" + e.getMessage());
|
// mOnSuccessAndFaultListener.onFault("error:" + e.getMessage());
|
||||||
dismissProgressDialog();
|
dismissProgressDialog();
|
||||||
progressDialog = null;
|
progressDialog = null;
|
||||||
|
|
|
@ -30,6 +30,7 @@ import com.novelbook.android.netutils.OnSuccessAndFaultSub;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.litepal.LitePal;
|
import org.litepal.LitePal;
|
||||||
|
import org.w3c.dom.Text;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -38,6 +39,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -198,14 +200,25 @@ public class BookUtil {
|
||||||
throw new RuntimeException("书本错误 code 001"); //无目标网站
|
throw new RuntimeException("书本错误 code 001"); //无目标网站
|
||||||
// return;
|
// return;
|
||||||
}
|
}
|
||||||
mSite =nvs.getSites()[0];
|
|
||||||
if(nvs.getSites().length > 0)
|
if(nvs.getSites().length > 0){
|
||||||
|
for (Site site:nvs.getSites() ) {
|
||||||
|
if(!TextUtils.isEmpty(mNovel.getDomain()) && site.getDomain().equals(mNovel.getDomain())){
|
||||||
|
mSite = site;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mSite ==null)
|
||||||
for (Site site:nvs.getSites() ) {
|
for (Site site:nvs.getSites() ) {
|
||||||
if(site.getSelectedByDefault()){
|
if(site.getSelectedByDefault()){
|
||||||
mSite = site;
|
mSite = site;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(mSite ==null)
|
||||||
|
mSite =nvs.getSites()[0];
|
||||||
|
}
|
||||||
getSiteRule();
|
getSiteRule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +265,7 @@ public class BookUtil {
|
||||||
}
|
}
|
||||||
},null));
|
},null));
|
||||||
}
|
}
|
||||||
private void getSiteRule() {
|
public void getSiteRule() {
|
||||||
mSiteRule = null;
|
mSiteRule = null;
|
||||||
BookSubscribe.getSiteRule(mSite.getDomain(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
|
BookSubscribe.getSiteRule(mSite.getDomain(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -296,22 +309,24 @@ public class BookUtil {
|
||||||
try {
|
try {
|
||||||
JSONObject siteJson = new JSONObject(result);
|
JSONObject siteJson = new JSONObject(result);
|
||||||
|
|
||||||
chaps = NovelParseUtil.getChapters(mSite.getMuluUrl(), siteJson);
|
mChapters = NovelParseUtil.getChapters(mSite.getMuluUrl(), siteJson,mSite.getDomain(),mNovel.getMaxAge(),mSiteRule.getEncoding());
|
||||||
|
|
||||||
if (chaps != null)
|
if (mChapters != null){
|
||||||
for (String s : chaps) {
|
for (Chapter chapter:mChapters) {
|
||||||
Log.d(TAG, "prepare book to get chaps readChaptersAsync: chapt: " + s);
|
Log.d(TAG, String.format("prepare book to get chaps readChaptersAsync %s-->%s",chapter.getChapterUrl(), chapter.getChapterName()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
Log.e(TAG, "prepare book error on parese :", e);
|
Log.e(TAG, "prepare book error on parese :", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chaps == null || chaps.length == 0) {
|
if (mChapters == null ||mChapters.size()== 0) {
|
||||||
readChaptersAsync();
|
readChaptersAsync();
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
|
handler.sendEmptyMessage(3);
|
||||||
Log.d(TAG,String.format("prepare book loadChapts----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
|
Log.d(TAG,String.format("prepare book loadChapts----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
|
||||||
mMuluStatus = MuluStatus.isDone;
|
mMuluStatus = MuluStatus.isDone;
|
||||||
Log.d(TAG, String.format("prepare book %s 章节信息完成.",mNovel.getName()) );
|
Log.d(TAG, String.format("prepare book %s 章节信息完成.",mNovel.getName()) );
|
||||||
|
@ -700,7 +715,9 @@ int muluRetryCount =0;
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
Log.d(TAG, String.format("prepare book %s 章节信息读取成功.thread %s",mNovel.getName(),Thread.currentThread().getName()) );
|
Log.d(TAG, String.format("prepare book %s 章节信息读取成功.thread %s",mNovel.getName(),Thread.currentThread().getName()) );
|
||||||
try {
|
try {
|
||||||
String bodyStr = body.string();
|
// String bodyStr = body.string();
|
||||||
|
String bodyStr =NovelParseUtil.enconding(body ,mSiteRule.getEncoding());
|
||||||
|
|
||||||
// Log.d(TAG, "onResponse: " +bodyStr);
|
// Log.d(TAG, "onResponse: " +bodyStr);
|
||||||
// Log.d(TAG,String.format("loadChaptContent----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
|
// Log.d(TAG,String.format("loadChaptContent----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
|
||||||
// long startTime2= new Date().getTime();
|
// long startTime2= new Date().getTime();
|
||||||
|
@ -785,20 +802,20 @@ int muluRetryCount =0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int next(boolean back){
|
public int next(boolean back,int chaptId){
|
||||||
position += 1;
|
position += 1;
|
||||||
if (position > tmpChaptLen){
|
if (position > tmpChaptLen){
|
||||||
position = tmpChaptLen;
|
position = tmpChaptLen;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
char result = chaptCurrent(); //current();
|
char result = chaptCurrent(chaptId); //current();
|
||||||
if (back) {
|
if (back) {
|
||||||
position -= 1;
|
position -= 1;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[] nextLine(){
|
/*public char[] nextLine(){
|
||||||
if (position >= tmpChaptLen){
|
if (position >= tmpChaptLen){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -816,7 +833,7 @@ int muluRetryCount =0;
|
||||||
line += wordChar;
|
line += wordChar;
|
||||||
}
|
}
|
||||||
return line.toCharArray();
|
return line.toCharArray();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public char[] preLine(){
|
public char[] preLine(){
|
||||||
if (position <= 0){
|
if (position <= 0){
|
||||||
|
@ -839,14 +856,17 @@ int muluRetryCount =0;
|
||||||
|
|
||||||
return line.toCharArray();
|
return line.toCharArray();
|
||||||
}
|
}
|
||||||
public char chaptCurrent(){
|
|
||||||
|
public char chaptCurrent(int chaptId){
|
||||||
// chapterNo = mChapters.size() < chapterNo ? 1 : chapterNo;
|
// chapterNo = mChapters.size() < chapterNo ? 1 : chapterNo;
|
||||||
// Log.d(TAG, String.format(" prepare book chaptCurrent() ,chapterNo %s, getChapters().size() %s " ,chapterNo , mChapters.size()) );
|
// Log.d(TAG, String.format(" prepare book chaptCurrent() ,chapterNo %s, getChapters().size() %s " ,chapterNo , mChapters.size()) );
|
||||||
char[] charArray = chaptChars(chapterNo);
|
char[] charArray = chaptChars(chaptId);
|
||||||
|
|
||||||
|
|
||||||
int i = (int)position-1;
|
int i = (int)position-1;
|
||||||
|
i =i>0?i:0;
|
||||||
i = i< charArray.length? i:charArray.length-1;
|
i = i< charArray.length? i:charArray.length-1;
|
||||||
|
|
||||||
return charArray[i];
|
return charArray[i];
|
||||||
}
|
}
|
||||||
public char current(){
|
public char current(){
|
||||||
|
@ -1258,6 +1278,7 @@ int muluRetryCount =0;
|
||||||
char[] block=null;
|
char[] block=null;
|
||||||
if(chaptCache.containsKey(Integer.valueOf(index))) {
|
if(chaptCache.containsKey(Integer.valueOf(index))) {
|
||||||
block = chaptCache .get(index).getData().get();
|
block = chaptCache .get(index).getData().get();
|
||||||
|
// Log.d(TAG, String.format("prepare book get block in cache, chapter: %s", index));
|
||||||
}
|
}
|
||||||
// Log.d(TAG, String.format("prepare book begin to load content for chapter %s", index));
|
// Log.d(TAG, String.format("prepare book begin to load content for chapter %s", index));
|
||||||
if (block == null) {
|
if (block == null) {
|
||||||
|
@ -1389,6 +1410,7 @@ int muluRetryCount =0;
|
||||||
new InputStreamReader(
|
new InputStreamReader(
|
||||||
new FileInputStream(file),
|
new FileInputStream(file),
|
||||||
charachterType
|
charachterType
|
||||||
|
// mSiteRule.getEncoding()
|
||||||
);
|
);
|
||||||
|
|
||||||
long l = reader.read(block);
|
long l = reader.read(block);
|
||||||
|
@ -1472,6 +1494,7 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response){
|
public void onResponse(Call call, Response response){
|
||||||
|
|
||||||
ResponseBody body = response.body();
|
ResponseBody body = response.body();
|
||||||
if (body != null ) {
|
if (body != null ) {
|
||||||
if(response.code()!=200){
|
if(response.code()!=200){
|
||||||
|
@ -1485,7 +1508,13 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String bodyStr = body.string();
|
Charset charset = body.contentType().charset();
|
||||||
|
if(charset!=null){
|
||||||
|
String name = charset.displayName();
|
||||||
|
}
|
||||||
|
// String bodyStr = body.string();
|
||||||
|
// bodyStr =NovelParseUtil.enconding(bodyStr,mSiteRule.getEncoding());
|
||||||
|
String bodyStr =NovelParseUtil.enconding(body,mSiteRule.getEncoding());
|
||||||
String title = chapter.getChapterName();
|
String title = chapter.getChapterName();
|
||||||
String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson);
|
String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson);
|
||||||
char[] buf = chapterContent.toCharArray();
|
char[] buf = chapterContent.toCharArray();
|
||||||
|
@ -1493,6 +1522,7 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte
|
||||||
file.createNewFile();
|
file.createNewFile();
|
||||||
|
|
||||||
final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), charachterType);//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
|
final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), charachterType);//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
|
||||||
|
// final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), mSiteRule.getEncoding() );//charachterType);//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
|
||||||
writer.write(buf);
|
writer.write(buf);
|
||||||
writer.close();
|
writer.close();
|
||||||
Log.d( TAG,String.format("prepare book loadChaptContent file created: %s, thread %s", file.getPath(), Thread.currentThread().getName()));
|
Log.d( TAG,String.format("prepare book loadChaptContent file created: %s, thread %s", file.getPath(), Thread.currentThread().getName()));
|
||||||
|
@ -1541,13 +1571,17 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte
|
||||||
.tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
|
.tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
|
||||||
.url(url)
|
.url(url)
|
||||||
.removeHeader("Pragma")
|
.removeHeader("Pragma")
|
||||||
.header("Cache-Control", "public, max-age=" + 0)
|
.header("Cache-Control", "public, max-age=" + maxAge)
|
||||||
// .header("Accept-Encoding","gzip, deflate, sdch")
|
|
||||||
.header("Accept-Language","zh-CN,zh;q=0.9")
|
.header("Accept-Language","zh-CN,zh;q=0.9")
|
||||||
.header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
|
.header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
|
||||||
.header( "Upgrade-Insecure-Requests", "1")
|
.header( "Upgrade-Insecure-Requests", "1")
|
||||||
|
// .header("content-type", "text/html; charset=utf-8")
|
||||||
;
|
;
|
||||||
|
/* if(mSiteRule!=null && !TextUtils.isEmpty(mSiteRule.getEncoding()) ){
|
||||||
|
builder.header("Accept-Encoding",mSiteRule.getEncoding());
|
||||||
|
}
|
||||||
|
*/
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package com.novelbook.android.utils;
|
package com.novelbook.android.utils;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.novelbook.android.db.Chapter;
|
import com.novelbook.android.db.Chapter;
|
||||||
|
import com.novelbook.android.db.SiteRule;
|
||||||
import com.novelbook.android.netutils.HttpMethods;
|
import com.novelbook.android.netutils.HttpMethods;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
|
@ -11,8 +12,12 @@ import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,6 +26,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
|
||||||
public class NovelParseUtil {
|
public class NovelParseUtil {
|
||||||
private static final String TAG=NovelParseUtil.class.getSimpleName();
|
private static final String TAG=NovelParseUtil.class.getSimpleName();
|
||||||
|
@ -93,6 +99,9 @@ public class NovelParseUtil {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static String getChapterContent(String html, JSONObject siteJson) throws JSONException {
|
public static String getChapterContent(String html, JSONObject siteJson) throws JSONException {
|
||||||
String chapterContentRegex = siteJson.getString("chapterContentRegex");
|
String chapterContentRegex = siteJson.getString("chapterContentRegex");
|
||||||
String text = REUtil.group(chapterContentRegex, html, 1);
|
String text = REUtil.group(chapterContentRegex, html, 1);
|
||||||
|
@ -127,7 +136,33 @@ public class NovelParseUtil {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static String[] getChapters(String url, JSONObject siteJson) throws JSONException {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<Chapter> getChaptersLst(String[] rows,String domain){
|
||||||
|
|
||||||
|
ArrayList<Chapter> lst = new ArrayList<Chapter>();
|
||||||
|
int j=0;
|
||||||
|
for (int i=0;i<rows.length;i+=2) {
|
||||||
|
j++;
|
||||||
|
Chapter chapter = new Chapter();
|
||||||
|
chapter.setChapterUrl( rows[i]);
|
||||||
|
chapter.setChapterName( rows[i+1]);
|
||||||
|
chapter.setDomain(domain);
|
||||||
|
chapter.setIndex(j); //第几章
|
||||||
|
lst.add(chapter);
|
||||||
|
|
||||||
|
}
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Chapter> getChapters(String url, JSONObject siteJson,String domain,int maxAage,String encoding) throws JSONException {
|
||||||
|
return getChaptersLst(getChapters(url,siteJson,maxAage,encoding),domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String[] getChapters(String url, JSONObject siteJson, int maxAge,String encoding) throws JSONException {
|
||||||
//if (!siteJson.keys().("chapterUrlRegexOnMulu")) return null;
|
//if (!siteJson.keys().("chapterUrlRegexOnMulu")) return null;
|
||||||
String chapterUrlRegexOnMulu = siteJson.getString("chapterUrlRegexOnMulu");
|
String chapterUrlRegexOnMulu = siteJson.getString("chapterUrlRegexOnMulu");
|
||||||
// if(TextUtils.isEmpty(chapterUrlRegexOnMulu)) return null;
|
// if(TextUtils.isEmpty(chapterUrlRegexOnMulu)) return null;
|
||||||
|
@ -152,7 +187,7 @@ public class NovelParseUtil {
|
||||||
Log.d(TAG, "to get chaps source:" + source );
|
Log.d(TAG, "to get chaps source:" + source );
|
||||||
if (source.startsWith("html:")) {
|
if (source.startsWith("html:")) {
|
||||||
String _url = source.substring("html:".length());
|
String _url = source.substring("html:".length());
|
||||||
source = access(_url);
|
source = access(_url,maxAge,encoding);
|
||||||
Log.d(TAG, "to get chaps source:" + source );
|
Log.d(TAG, "to get chaps source:" + source );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,33 +276,76 @@ public class NovelParseUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static String access(String url) {
|
private static String access(String url,int maxAge,String encoding) {
|
||||||
Request.Builder builder = new Request.Builder()
|
Request.Builder builder = new Request.Builder()
|
||||||
// .tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
|
// .tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
|
||||||
.url(url)
|
.url(url)
|
||||||
.removeHeader("Pragma")
|
.removeHeader("Pragma")
|
||||||
.header("Cache-Control", "public, max-age=" + 0)
|
.header("Cache-Control", "public, max-age=" + maxAge)
|
||||||
// .header("Accept-Encoding","gzip, deflate, sdch")
|
// .header("Accept-Encoding","gzip, deflate, sdch")
|
||||||
.header("Accept-Language","zh-CN,zh;q=0.9")
|
// .header("Accept-Language","zh-CN,zh;q=0.9")
|
||||||
.header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
|
// .header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
|
||||||
.header( "Upgrade-Insecure-Requests", "1")
|
// .header( "Upgrade-Insecure-Requests", "1")
|
||||||
|
// .header("content-type", "text/html; charset=utf-8")
|
||||||
;
|
;
|
||||||
|
|
||||||
Request request =builder.build() ;
|
Request request =builder.build() ;
|
||||||
|
Response response = null;
|
||||||
try {
|
try {
|
||||||
Response response = HttpMethods.getOkClient().newCall(request).execute();
|
response = HttpMethods.getOkClient().newCall(request).execute();
|
||||||
String s =response.body().string();
|
//String s =response.body().string();
|
||||||
|
|
||||||
|
String s = enconding(response.body(),encoding); //new String(response.body().bytes(), encoding);
|
||||||
|
// response.body().close();
|
||||||
|
long st = new java.util.Date().getTime();
|
||||||
Log.d(TAG, "to get chaps access result:" + s );
|
Log.d(TAG, "to get chaps access result:" + s );
|
||||||
return s;
|
return s;
|
||||||
|
// return enconding(s,encoding);
|
||||||
|
// return info;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
Log.e(TAG, "access: ", e);
|
||||||
|
}finally {
|
||||||
|
if(response!=null)
|
||||||
|
response.body().close();
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String enconding(ResponseBody body, String encode) throws UnsupportedEncodingException {
|
||||||
|
String s="";
|
||||||
|
try{
|
||||||
|
Charset charset = body.contentType().charset();
|
||||||
|
if(charset!=null){
|
||||||
|
s= body.string();
|
||||||
|
}else {
|
||||||
|
s= new String(body.bytes(), encode);
|
||||||
|
}
|
||||||
|
}catch (Exception er){
|
||||||
|
|
||||||
|
}finally {
|
||||||
|
body.close();
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
|
||||||
|
/* Log.d(TAG, " encoding covert from :" +source );
|
||||||
|
long st = new java.util.Date().getTime();
|
||||||
|
byte[] b = source.getBytes("utf-8");
|
||||||
|
// String info = new String(b, "utf-8");
|
||||||
|
String info = new String(b);
|
||||||
|
Log.d(TAG, " encoding covert to :" +info );
|
||||||
|
Log.d(TAG, "encoding covert :" + encode +", cost " +( new Date().getTime() -st));
|
||||||
|
return info;*/
|
||||||
|
|
||||||
|
/* long st = new java.util.Date().getTime();
|
||||||
|
byte[] b = source.getBytes(encode);
|
||||||
|
// String info = new String(b, "utf-8");
|
||||||
|
String info = new String(b,"utf-8");
|
||||||
|
Log.d(TAG, " encoding covert to :" +info );
|
||||||
|
Log.d(TAG, "encoding covert :" + encode +", cost " +( new Date().getTime() -st));
|
||||||
|
return info;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -380,7 +380,7 @@ public class PageFactory implements ChangeSource{
|
||||||
int pageNo =0;
|
int pageNo =0;
|
||||||
while(length <chars.length ) {
|
while(length <chars.length ) {
|
||||||
pageNo++;
|
pageNo++;
|
||||||
TRPage page = getNextChapterPage(length);
|
TRPage page = getNextChapterPage(chaptId,length);
|
||||||
// Log.d(TAG,"prepare book page.getBegin :" + page.getBegin()+ ",chapter length "+ mBookUtil.getBookLen());
|
// Log.d(TAG,"prepare book page.getBegin :" + page.getBegin()+ ",chapter length "+ mBookUtil.getBookLen());
|
||||||
|
|
||||||
// if(page.getBegin() == mBookUtil.getBookLen() ){ //最后一页空白的情况。。。
|
// if(page.getBegin() == mBookUtil.getBookLen() ){ //最后一页空白的情况。。。
|
||||||
|
@ -401,13 +401,13 @@ public class PageFactory implements ChangeSource{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public TRPage getNextChapterPage(long position){
|
public TRPage getNextChapterPage(int chaptId,long position){
|
||||||
mBookUtil.setPostition(position);
|
mBookUtil.setPostition(position);
|
||||||
|
|
||||||
TRPage trPage = new TRPage();
|
TRPage trPage = new TRPage();
|
||||||
trPage.setBegin(position +1);
|
trPage.setBegin(position +1);
|
||||||
// Log.d(TAG,"page postion next begin:" + (position + 1) + "");
|
// Log.d(TAG,"page postion next begin:" + (position + 1) + "");
|
||||||
trPage.setLines(getNextLines());
|
trPage.setLines(getNextLines(chaptId));
|
||||||
// Log.d(TAG,"page postion next end:" +mBookUtil.getPosition() + "");
|
// Log.d(TAG,"page postion next end:" +mBookUtil.getPosition() + "");
|
||||||
trPage.setEnd(mBookUtil.getPosition());
|
trPage.setEnd(mBookUtil.getPosition());
|
||||||
return trPage;
|
return trPage;
|
||||||
|
@ -442,6 +442,7 @@ public class PageFactory implements ChangeSource{
|
||||||
}
|
}
|
||||||
public void changeSource(String domain,int chapId,String chapTitle) {
|
public void changeSource(String domain,int chapId,String chapTitle) {
|
||||||
fileRetryCnt.clear();
|
fileRetryCnt.clear();
|
||||||
|
chaptMap.clear();
|
||||||
mBookUtil.changeSource(domain, chapId, chapTitle);
|
mBookUtil.changeSource(domain, chapId, chapTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1070,7 +1071,7 @@ public static boolean busy(){
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean showChapTitleOnTopWhenNextPage =false;
|
boolean showChapTitleOnTopWhenNextPage =false;
|
||||||
public List<String> getNextLines(){
|
public List<String> getNextLines(int chaptId){
|
||||||
List<String> lines = new ArrayList<>();
|
List<String> lines = new ArrayList<>();
|
||||||
float width = 0;
|
float width = 0;
|
||||||
float height = 0;
|
float height = 0;
|
||||||
|
@ -1079,8 +1080,8 @@ public static boolean busy(){
|
||||||
lines.add("\n");lines.add("\n");
|
lines.add("\n");lines.add("\n");
|
||||||
}
|
}
|
||||||
calculateLineCount();
|
calculateLineCount();
|
||||||
while (mBookUtil.next(true) != -1){
|
while (mBookUtil.next(true,chaptId) != -1){
|
||||||
char word = (char) mBookUtil.next(false);
|
char word = (char) mBookUtil.next(false,chaptId);
|
||||||
//判断是否换行
|
//判断是否换行
|
||||||
if ((word + "" ).equals("\n") ){// if ((word + "" ).equals("\r") && (((char) mBookUtil.next(true)) + "").equals("\n")){
|
if ((word + "" ).equals("\n") ){// if ((word + "" ).equals("\r") && (((char) mBookUtil.next(true)) + "").equals("\n")){
|
||||||
// mBookUtil.next(false);
|
// mBookUtil.next(false);
|
||||||
|
@ -1570,5 +1571,9 @@ public static boolean busy(){
|
||||||
}
|
}
|
||||||
return new Novel();
|
return new Novel();
|
||||||
}
|
}
|
||||||
|
public void refreshCate(){
|
||||||
|
mBookUtil.getChapters().clear();
|
||||||
|
mBookUtil.getSiteRule();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
style="@style/TextViewNovelTitle"
|
style="@style/TextViewNovelTitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
<android.support.v4.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipeLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@+id/lv_catalogue"
|
android:id="@+id/lv_catalogue"
|
||||||
|
@ -36,7 +41,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:divider="@color/list_item_divider"
|
android:divider="@color/list_item_divider"
|
||||||
android:dividerHeight="1dp" />
|
android:dividerHeight="1dp" />
|
||||||
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnRefresh"
|
android:id="@+id/btnRefresh"
|
||||||
android:layout_width="100dp"
|
android:layout_width="100dp"
|
||||||
|
|
Loading…
Reference in New Issue