mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-15 02:18:04 -04:00
Merge branch 'komaz-issues/52'
* komaz-issues/52: Fixing indentation. Create new database when upgradingto version >= 3 Handle database upgrade Introducing use of squidb for persisting recent-search history. Use simplexml in MetaLinkNetworkEntity for parsing
This commit is contained in:
commit
dfd6a033f7
@ -47,6 +47,7 @@ dependencies {
|
||||
compile files("$buildDir/native-libs/native-libs.jar")
|
||||
|
||||
// compile fileTree(dir: '.', include: 'content-libs.jar') // DO NOT REMOVE !!
|
||||
testCompile 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
android {
|
||||
@ -80,6 +81,11 @@ android {
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
}
|
||||
|
||||
test {
|
||||
java.srcDirs = ['test']
|
||||
resources.srcDirs = ['test']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package org.kiwix.kiwixmobile;
|
||||
import android.app.Application;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.kiwix.kiwixmobile.network.KiwixService;
|
||||
import org.kiwix.kiwixmobile.network.converter.MetaLinkConverterFactory;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
|
||||
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;
|
||||
@ -22,7 +21,6 @@ public class KiwixApplication extends Application {
|
||||
private void createRetrofitService() {
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl("http://kiwix.org/")
|
||||
.addConverterFactory(MetaLinkConverterFactory.create())
|
||||
.addConverterFactory(SimpleXmlConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))
|
||||
.build();
|
||||
|
@ -56,7 +56,7 @@ public class DownloadService extends Service {
|
||||
private void downloadBook(String url) {
|
||||
kiwixService.getMetaLinks(url)
|
||||
.subscribeOn(AndroidSchedulers.mainThread())
|
||||
.flatMap(metaLink -> getMetaLinkContentLength(metaLink.getRelevantUrl()))
|
||||
.flatMap(metaLink -> getMetaLinkContentLength(metaLink.getRelevantUrl().getValue()))
|
||||
.flatMap(pair -> Observable.from(ChunkUtils.getChunks(pair.first, pair.second)))
|
||||
.concatMap(this::downloadChunk)
|
||||
.distinctUntilChanged()
|
||||
|
@ -1,19 +1,111 @@
|
||||
package org.kiwix.kiwixmobile.library.entity;
|
||||
|
||||
import org.simpleframework.xml.Attribute;
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.ElementList;
|
||||
import org.simpleframework.xml.ElementMap;
|
||||
import org.simpleframework.xml.Root;
|
||||
import org.simpleframework.xml.Text;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Root(strict = false, name="metalink")
|
||||
public class MetaLinkNetworkEntity {
|
||||
private List<String> urls;
|
||||
|
||||
public List<String> getUrls() {
|
||||
return urls;
|
||||
public List<Url> getUrls() {
|
||||
return file.urls;
|
||||
}
|
||||
|
||||
public String getRelevantUrl() {
|
||||
return urls.get(0);
|
||||
public Url getRelevantUrl() {
|
||||
return file.urls.get(0);
|
||||
}
|
||||
|
||||
public void setUrls(List<String> urls) {
|
||||
this.urls = urls;
|
||||
@Element
|
||||
private FileElement file;
|
||||
|
||||
public FileElement getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Root(strict=false)
|
||||
public static class FileElement {
|
||||
@Attribute
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@ElementList(inline = true, entry = "url")
|
||||
private List<Url> urls;
|
||||
|
||||
@Element
|
||||
private int size;
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@ElementMap(entry = "hash", key = "type", attribute = true, inline = true)
|
||||
private Map<String, String> hashes;
|
||||
|
||||
@Element
|
||||
private Pieces pieces;
|
||||
|
||||
public int getPieceLength() {
|
||||
return pieces.length;
|
||||
}
|
||||
|
||||
public String getPieceHashType() {
|
||||
return pieces.hashType;
|
||||
}
|
||||
|
||||
public List<String> getPieceHashes() {
|
||||
return pieces.pieceHashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file hash
|
||||
* @param type Hash type as defined in metalink file
|
||||
* @return Hash value or {@code null}
|
||||
*/
|
||||
public String getHash(String type) {
|
||||
return hashes.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Pieces {
|
||||
@Attribute
|
||||
private int length;
|
||||
|
||||
@Attribute(name="type")
|
||||
private String hashType;
|
||||
|
||||
@ElementList(inline = true, entry="hash")
|
||||
private List<String> pieceHashes;
|
||||
}
|
||||
|
||||
public static class Url {
|
||||
@Attribute
|
||||
private String location;
|
||||
|
||||
@Attribute
|
||||
private int priority;
|
||||
|
||||
@Text
|
||||
private String value;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Square, Inc.
|
||||
*
|
||||
* 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 org.kiwix.kiwixmobile.network.converter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
import org.kiwix.kiwixmobile.library.entity.MetaLinkNetworkEntity;
|
||||
import retrofit2.Converter;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
public final class MetaLinkConverterFactory extends Converter.Factory {
|
||||
public static MetaLinkConverterFactory create() {
|
||||
return new MetaLinkConverterFactory();
|
||||
}
|
||||
|
||||
private MetaLinkConverterFactory() {
|
||||
}
|
||||
|
||||
@Override public Converter<?, RequestBody> requestBodyConverter(Type type,
|
||||
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
|
||||
Retrofit retrofit) {
|
||||
if (type == MetaLinkNetworkEntity.class) {
|
||||
return MetaLinkConverter.INSTANCE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static final class MetaLinkConverter implements Converter<ResponseBody, MetaLinkNetworkEntity> {
|
||||
static final MetaLinkConverter INSTANCE = new MetaLinkConverter();
|
||||
private static final Pattern pattern = Pattern.compile("<url.*?>(.*?)</url>");
|
||||
|
||||
@Override public MetaLinkNetworkEntity convert(ResponseBody value) throws IOException {
|
||||
List<String> urls = new ArrayList<>();
|
||||
|
||||
Matcher matcher = pattern.matcher(value.string());
|
||||
while (matcher.find()) {
|
||||
urls.add(matcher.group(1));
|
||||
}
|
||||
if (!urls.isEmpty() && urls.size() >= 2) urls = urls.subList(1, urls.size());
|
||||
|
||||
MetaLinkNetworkEntity metaLinkNetworkEntity = new MetaLinkNetworkEntity();
|
||||
metaLinkNetworkEntity.setUrls(urls);
|
||||
|
||||
return metaLinkNetworkEntity;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package org.kiwix.kiwixmobile.library.entity;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.junit.Test;
|
||||
import org.simpleframework.xml.Serializer;
|
||||
import org.simpleframework.xml.core.Persister;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class MetaLinkNetworkEntityTest {
|
||||
private static Matcher<MetaLinkNetworkEntity.Url> url(
|
||||
String location, int priority, String value) {
|
||||
return new UrlMatcher(location, priority, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws Exception {
|
||||
Serializer serializer = new Persister();
|
||||
final MetaLinkNetworkEntity result = serializer.read(
|
||||
MetaLinkNetworkEntity.class,
|
||||
MetaLinkNetworkEntityTest.class.getResourceAsStream(
|
||||
"wikipedia_af_all_nopic_2016-05.zim.meta4"
|
||||
));
|
||||
assertThat(result.getUrls().size(), is(5));
|
||||
assertThat(result.getUrls(), hasItems(
|
||||
url("us", 1, "http://ftpmirror.your.org/pub/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"),
|
||||
url("gb", 2, "http://www.mirrorservice.org/sites/download.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"),
|
||||
url("us", 3, "http://download.wikimedia.org/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"),
|
||||
url("de", 4, "http://mirror.netcologne.de/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"),
|
||||
url("fr", 5, "http://mirror3.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim")
|
||||
));
|
||||
|
||||
// Basic file attributes
|
||||
assertThat(result.getFile().getName(), is("wikipedia_af_all_nopic_2016-05.zim"));
|
||||
assertThat(result.getFile().getSize(), is(63973123));
|
||||
|
||||
// File hashes
|
||||
assertThat(result.getFile().getHash("md5"), is("6f06866b61c4a921b57f28cfd4307220"));
|
||||
assertThat(result.getFile().getHash("sha-1"), is("8aac4c7f89e3cdd45b245695e19ecde5aac59593"));
|
||||
assertThat(result.getFile().getHash("sha-256"),
|
||||
is("83126775538cf588a85edb10db04d6e012321a2025278a08a084b258849b3a5c"));
|
||||
|
||||
// Pieces
|
||||
assertThat(result.getFile().getPieceHashType(), is("sha-1"));
|
||||
assertThat(result.getFile().getPieceLength(), is(1048576));
|
||||
|
||||
// Check only the first and the last elements of the piece hashes
|
||||
assertThat(result.getFile().getPieceHashes().size(), is(62));
|
||||
assertThat(result.getFile().getPieceHashes().get(0),
|
||||
is("f36815d904d4fd563aaef4ee6ef2600fb1fd70b2"));
|
||||
assertThat(result.getFile().getPieceHashes().get(61),
|
||||
is("8055e515aa6e78f2810bbb0e0cd07330838b8920"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemented as a matcher only to avoid putting extra code into {@code MetaLinkNetworkEntity}.
|
||||
* However in case {@code equals} and {@code hashCode} methods are added to
|
||||
* {@code MetaLinkNetworkEntity.Url} class itself, this Matcher should be deleted.
|
||||
*/
|
||||
private static class UrlMatcher extends TypeSafeMatcher<MetaLinkNetworkEntity.Url> {
|
||||
private String location;
|
||||
private int priority;
|
||||
private String value;
|
||||
|
||||
public UrlMatcher(String location, int priority, String value) {
|
||||
this.location = location;
|
||||
this.priority = priority;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(MetaLinkNetworkEntity.Url item) {
|
||||
return location.equals(item.getLocation()) && priority == item.getPriority()
|
||||
&& value.equals(item.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(String.format(
|
||||
"Url (location=%s, priority=%d, value=%s", location, priority, value));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metalink xmlns="urn:ietf:params:xml:ns:metalink">
|
||||
<generator>MirrorBrain/2.18.1</generator>
|
||||
<origin dynamic="true">http://download.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim.meta4</origin>
|
||||
<published>2016-06-08T08:59:18Z</published>
|
||||
<publisher>
|
||||
<name>Kiwix project</name>
|
||||
<url>http://www.kiwix.org</url>
|
||||
</publisher>
|
||||
|
||||
<file name="wikipedia_af_all_nopic_2016-05.zim">
|
||||
<size>63973123</size>
|
||||
|
||||
<!-- <mtime>1462622396</mtime> -->
|
||||
|
||||
<!-- internal id: 756021 -->
|
||||
<hash type="md5">6f06866b61c4a921b57f28cfd4307220</hash>
|
||||
<hash type="sha-1">8aac4c7f89e3cdd45b245695e19ecde5aac59593</hash>
|
||||
<hash type="sha-256">83126775538cf588a85edb10db04d6e012321a2025278a08a084b258849b3a5c</hash>
|
||||
<pieces length="1048576" type="sha-1">
|
||||
<hash>f36815d904d4fd563aaef4ee6ef2600fb1fd70b2</hash>
|
||||
<hash>cd34a8a85ed1dd275417ce224ff0cd8d9893d101</hash>
|
||||
<hash>7702114faf59441937c9075ad695fad61cdb13f3</hash>
|
||||
<hash>532553bfb04c870375a53368b17838e50b169ab8</hash>
|
||||
<hash>fcda3eba296502965015ef3f07b05adeb4d95dfc</hash>
|
||||
<hash>97af1a7b1327a6f13dfc63524c63077c4aaa1278</hash>
|
||||
<hash>4c02b16d3d0cb1acc5b0eb02a46e3047245ca65c</hash>
|
||||
<hash>163927a9e7405b20c0544d06243baecfdf3c13d3</hash>
|
||||
<hash>1d4ccf5570fecefc93793aa1ebb73d95eb46cf03</hash>
|
||||
<hash>a0e5200bde74ba58c7318e15a34d5f891fb36841</hash>
|
||||
<hash>e862a19ce5a4066efdcc15bf3c74462292251171</hash>
|
||||
<hash>1c964b3029b6eda5ddff6815bf5298ca9a4c4196</hash>
|
||||
<hash>29f52efd444b496fc55c99541de62823605bdce7</hash>
|
||||
<hash>d5ae5e610f0b2f102bc16d7eeea55cacf259dda8</hash>
|
||||
<hash>b7e0102f182a84d76c3a8ca02d0e9319a320eed6</hash>
|
||||
<hash>bd63b665f1ac5620226481bacbe4dee1d31d48ba</hash>
|
||||
<hash>54393351f78e24c4ebb4dbfd22fcdfff279f39fb</hash>
|
||||
<hash>8845733b1da2876ad81aa1f7596dfd0e49bcc293</hash>
|
||||
<hash>94c2bb5e297a1c61bd1e4a3b47a2ffa8457dc9aa</hash>
|
||||
<hash>b2c1229eb3ffa88c71f0584c9714b7cf2d7df091</hash>
|
||||
<hash>d0978cf7aaba0320442673fc47f400e43df84a99</hash>
|
||||
<hash>5b8e68db7197089a78e92eb77f1c63859d098b1b</hash>
|
||||
<hash>d4ff1f37c101735c81a06ebd98e1c3be465e0314</hash>
|
||||
<hash>e9399f2c1f883816d3007765443cd38a1b4c6f9f</hash>
|
||||
<hash>b6fa56a9dc6893bd67deebd14e9f2ccd42d63355</hash>
|
||||
<hash>73efed5e8fd6480fece063826d62241783126b63</hash>
|
||||
<hash>b24ec4bd6f1f6ad2de9724275ac141c92692edd2</hash>
|
||||
<hash>3d35dee6ee7e1add3e8f30fe601f4f74ed11e704</hash>
|
||||
<hash>9af07844246402bc6e28f37f8eb8c0329033a874</hash>
|
||||
<hash>1be6178907a740670d8e61f72ebc8d47860015ce</hash>
|
||||
<hash>6e954cc098392cf7f515e07f4d666d8b0a5fe329</hash>
|
||||
<hash>e9f09f347f07585338073fea96f8d009a5aa3e0d</hash>
|
||||
<hash>a48801add4c60733a023bdcce5e62aacb33becf0</hash>
|
||||
<hash>90ca6abeeb08fbc136f1d0234741ca6b506869bc</hash>
|
||||
<hash>7c426983069ea0556168f9e7343426f79d233bc1</hash>
|
||||
<hash>18e893707d86bb778f9be3957e2645502ae1469d</hash>
|
||||
<hash>c7a984439cb7e7fbbc805ea9eb77bebcfbaa25a5</hash>
|
||||
<hash>9614ca49b5611494e4aaa0a3ffd3e23f5bfae86a</hash>
|
||||
<hash>d344c4cd8db6c0859eb00ba90cdeb1e12b9922c4</hash>
|
||||
<hash>ef777338b04c4b638721e1a043c3ae433a885c82</hash>
|
||||
<hash>04504c63113f7719f5ac13c8e30f1feec4648268</hash>
|
||||
<hash>1411ad174573f8c2a9a2d33c33f77f776db40f35</hash>
|
||||
<hash>bc771262c4abf687b49321c83fd4613dbdcc1aa3</hash>
|
||||
<hash>6762c76f99280283fa73037a0358efe5fd903eee</hash>
|
||||
<hash>8ba56ea08fe4c2f9e76ee8273ce9dad4c4bd977a</hash>
|
||||
<hash>97d8246b1db42afb9048109f920811fb5e723e71</hash>
|
||||
<hash>6c59c23baeb706f6902f5a8dc822bcf932721cdc</hash>
|
||||
<hash>1dff0732d971bc25af5afa9768493f435e5ab5d0</hash>
|
||||
<hash>133ff15a2992b0d5337eeddc62da839f86cee1e0</hash>
|
||||
<hash>0590bc490e4f12782849b8b36b87e1b68becdb83</hash>
|
||||
<hash>705e5c62c96c6b41a9cfea97796ebdcc981145a6</hash>
|
||||
<hash>e03ba6cf2deba1dfc8d781e4b8d0c602e033eea4</hash>
|
||||
<hash>a5c46e2093d7c138df4553bfc92604de91b8fe89</hash>
|
||||
<hash>035f0bd63b253c88a5ef7efaea96b3ee664e6f91</hash>
|
||||
<hash>3b4732487b464d6164d9e460d990dcf8de8b499c</hash>
|
||||
<hash>3453494c2188f5bee8a86a7b3626129e61a8bb21</hash>
|
||||
<hash>47a062cdd2f7024f6f6ebffe6ade5ca9474932ea</hash>
|
||||
<hash>5c30eee23b5b75680958760472c5c39aaaab108c</hash>
|
||||
<hash>c93ae5c2faf3f3a898e01f5c9aef1d57f2969990</hash>
|
||||
<hash>debf6ed9bbfbc9db4505d89dc74f871049d5c918</hash>
|
||||
<hash>3d0c0800396e5305ff1ddabba2371f817ec4839c</hash>
|
||||
<hash>8055e515aa6e78f2810bbb0e0cd07330838b8920</hash>
|
||||
</pieces>
|
||||
|
||||
|
||||
<!-- Found 7 mirrors: 0 in the same network prefix, 0 in the same autonomous system,
|
||||
0 handling this country, 0 in the same region, 5 elsewhere -->
|
||||
|
||||
<!-- Mirrors in the same network (unknown): -->
|
||||
|
||||
<!-- Mirrors in the same AS (unknown): -->
|
||||
|
||||
<!-- Mirrors which handle this country (unknown): -->
|
||||
|
||||
<!-- Mirrors in the same continent (unknown): -->
|
||||
|
||||
<!-- Mirrors in the rest of the world: -->
|
||||
<url location="us" priority="1">http://ftpmirror.your.org/pub/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim</url>
|
||||
<url location="gb" priority="2">http://www.mirrorservice.org/sites/download.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim</url>
|
||||
<url location="us" priority="3">http://download.wikimedia.org/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim</url>
|
||||
<url location="de" priority="4">http://mirror.netcologne.de/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim</url>
|
||||
<url location="fr" priority="5">http://mirror3.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim</url>
|
||||
</file>
|
||||
</metalink>
|
Loading…
x
Reference in New Issue
Block a user