├── app
├── .gitignore
├── src
│ └── main
│ │ ├── ic_launcher-web.png
│ │ ├── res
│ │ ├── drawable-xxhdpi
│ │ │ ├── ic_book.jpg
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_menu_check.png
│ │ ├── drawable-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_menu_check.png
│ │ ├── drawable-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_menu_check.png
│ │ ├── drawable-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_menu_check.png
│ │ ├── values-zh-rCN
│ │ │ └── strings.xml
│ │ ├── anim
│ │ │ └── pocket_interpolator.xml
│ │ ├── values
│ │ │ ├── attrs.xml
│ │ │ ├── strings.xml
│ │ │ ├── dimens.xml
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── drawable
│ │ │ └── frament_subject_item_bg.xml
│ │ ├── menu
│ │ │ └── main.xml
│ │ ├── layout
│ │ │ ├── toolbar_default.xml
│ │ │ ├── fragment_navigation_drawer.xml
│ │ │ ├── fragment_subject.xml
│ │ │ ├── drawer_row.xml
│ │ │ ├── fragment_book.xml
│ │ │ ├── activity_main.xml
│ │ │ ├── activity_main_blacktoolbar.xml
│ │ │ ├── fragment_subject_item.xml
│ │ │ └── activity_main_topdrawer.xml
│ │ └── values-v21
│ │ │ └── styles.xml
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── snowdream
│ │ │ └── android
│ │ │ └── app
│ │ │ └── books
│ │ │ ├── NavigationDrawerCallbacks.java
│ │ │ ├── NavigationItem.java
│ │ │ ├── controller
│ │ │ ├── CallBack.java
│ │ │ └── BookManager.java
│ │ │ ├── entity
│ │ │ ├── BookItem.java
│ │ │ ├── Subject.java
│ │ │ └── Book.java
│ │ │ ├── SubjectFragment.java
│ │ │ ├── MainApplication.java
│ │ │ ├── SubjectAdapter.java
│ │ │ ├── MainActivity.java
│ │ │ ├── ScrimInsetsFrameLayout.java
│ │ │ ├── NavigationDrawerAdapter.java
│ │ │ ├── BookFragment.java
│ │ │ └── NavigationDrawerFragment.java
│ │ └── AndroidManifest.xml
├── gradle.properties
├── build.gradle
└── proguard-rules.txt
├── settings.gradle
├── config
├── sign.gradle
├── android-library.gradle
├── android.gradle
└── maven_push.gradle
├── docs
├── preview
│ ├── android-books.png
│ ├── Screenshot_2015-01-26-20-38-32.png
│ ├── Screenshot_2015-01-26-20-38-42.png
│ ├── Screenshot_2015-01-26-20-38-48.png
│ └── Screenshot_2015-01-26-20-38-56.png
├── specifications
│ └── book.json
└── test
│ ├── computer.json
│ ├── education.json
│ ├── foreign.json
│ └── recomend.json
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── .gitignore
├── README.md
├── gradlew.bat
├── gradlew
└── LICENSE
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/config/sign.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'signing'
2 |
3 |
4 | signing {
5 | sign configurations.archives
6 | }
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/docs/preview/android-books.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/docs/preview/android-books.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_book.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-xxhdpi/ic_book.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/docs/preview/Screenshot_2015-01-26-20-38-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/docs/preview/Screenshot_2015-01-26-20-38-32.png
--------------------------------------------------------------------------------
/docs/preview/Screenshot_2015-01-26-20-38-42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/docs/preview/Screenshot_2015-01-26-20-38-42.png
--------------------------------------------------------------------------------
/docs/preview/Screenshot_2015-01-26-20-38-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/docs/preview/Screenshot_2015-01-26-20-38-48.png
--------------------------------------------------------------------------------
/docs/preview/Screenshot_2015-01-26-20-38-56.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/docs/preview/Screenshot_2015-01-26-20-38-56.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_menu_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-hdpi/ic_menu_check.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_menu_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-mdpi/ic_menu_check.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_menu_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-xhdpi/ic_menu_check.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_menu_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snowdream/snowdream-books-android/HEAD/app/src/main/res/drawable-xxhdpi/ic_menu_check.png
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 雪梦图书
6 |
7 |
--------------------------------------------------------------------------------
/app/gradle.properties:
--------------------------------------------------------------------------------
1 | PACKAGE_NAME=com.github.snowdream.apps.books
2 | POM_GROUP_ID=com.github.snowdream.android.apps
3 | POM_ARTIFACT_ID=books
4 | POM_NAME=books
5 | POM_PACKAGING=apk
6 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/pocket_interpolator.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Dec 03 22:12:34 CST 2014
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/NavigationDrawerCallbacks.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books;
2 |
3 | /**
4 | * Created by poliveira on 27/10/2014.
5 | */
6 | public interface NavigationDrawerCallbacks {
7 | void onNavigationDrawerItemSelected(int position);
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Snowdream Books
4 | Menu opened
5 | Menu closed
6 | Settings
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/frament_subject_item_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/toolbar_default.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
8 | 240dp
9 | 4dp
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_navigation_drawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_subject.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'eclipse'
2 | apply plugin: 'idea'
3 | apply from: '../config/android.gradle'
4 |
5 | dependencies {
6 | compile 'com.android.support:support-v4:21.0.3'
7 | //noinspection GradleDependency
8 | compile "com.android.support:appcompat-v7:21.0.0"
9 | compile 'com.android.support:recyclerview-v7:21.0.0'
10 | compile 'com.google.android.gms:play-services:6.5.87'
11 | compile 'com.github.snowdream.android.util:log:1.0.4'
12 | compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.3'
13 | compile 'com.loopj.android:android-async-http:1.4.6'
14 | compile "org.parceler:parceler-api:0.2.15"
15 | provided "org.parceler:parceler:0.2.15"
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/drawer_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
20 |
--------------------------------------------------------------------------------
/docs/specifications/book.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "book": [
4 | {
5 | "language":"zh",
6 | "author":"",
7 | "country":"CN",
8 | "title": "test",
9 | "desc":"testbook",
10 | "default":true ,
11 | "url":"http://snowdream86.gitbooks.io/github-cheat-sheet/?lang=zh",
12 | "img":"https://sm3lir.cloudimage.io/s/cdn/x/https://www.gitbook.com/cover/book/snowdream86/github-cheat-sheet?build=1416974605786"
13 |
14 | },
15 | {
16 | "language":"en",
17 | "author":"",
18 | "country":"US",
19 | "title": "test",
20 | "desc":"testbook",
21 | "default":false,
22 | "url":"http://snowdream86.gitbooks.io/github-cheat-sheet/?lang=zh",
23 | "img":"https://sm3lir.cloudimage.io/s/cdn/x/https://www.gitbook.com/cover/book/snowdream86/github-cheat-sheet?build=1416974605786"
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/NavigationItem.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books;
2 |
3 | import android.graphics.drawable.Drawable;
4 | import com.github.snowdream.android.app.books.entity.Subject;
5 |
6 | /**
7 | * Created by poliveira on 24/10/2014.
8 | */
9 | public class NavigationItem {
10 | private Subject mSubject;
11 | private Drawable mDrawable;
12 |
13 | public NavigationItem(Subject subject, Drawable drawable) {
14 | mSubject = subject;
15 | mDrawable = drawable;
16 | }
17 |
18 | public Subject getSubject() {
19 | return mSubject;
20 | }
21 |
22 | public void setText(Subject subject) {
23 | mSubject = subject;
24 | }
25 |
26 | public Drawable getDrawable() {
27 | return mDrawable;
28 | }
29 |
30 | public void setDrawable(Drawable drawable) {
31 | mDrawable = drawable;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/controller/CallBack.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Snowdream Mobile
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.snowdream.android.app.books.controller;
18 |
19 |
20 | /**
21 | * Created by hui.yang on 2014/12/7.
22 | */
23 | public interface CallBack {
24 | public void callback(T result);
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 | #3F51B5
12 | #3F51B5
13 | #3F51B5
14 | #F2F2F2
15 | #DEDEDE
16 | #FFFFFF
17 | #000000
18 |
19 | #ffdbdbdb
20 | #00000000
21 | #FFFFFFFF
22 | #000000
23 | #E0E0E0
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_book.xml:
--------------------------------------------------------------------------------
1 |
9 |
15 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
19 |
20 |
24 |
25 |
--------------------------------------------------------------------------------
/app/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/snowdream/bin/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the ProGuard
5 | # include property in project.properties.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 | -keep public class com.google.android.gms.ads.**{
19 | public *;
20 | }
21 |
22 | -keep public class com.google.ads.**{
23 | public *;
24 | }
25 |
26 | -keep class com.nostra13.universalimageloader.** { *; }
27 | -keep class org.parceler.** { *; }
28 | -keep class com.loopj.android.** { *; }
29 |
30 | -dontwarn com.nostra13.universalimageloader.**
31 | -dontwarn org.parceler.**
32 | -dontwarn com.loopj.android.**
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Set Gradle settings which apply to all modules here.
2 | PACKAGE_NAME=com.github.snowdream.apps.books
3 | VERSION_NAME=1.2
4 | VERSION_CODE=4
5 | MIN_SDK_VERSION=9
6 | TARGET_SDK_VERSION=21
7 | COMPILE_SDK_VERSION=21
8 | BUILD_TOOLS_VERSION=21.1.2
9 |
10 |
11 |
12 | POM_GROUP_ID=com.github.snowdream.android.apps
13 | POM_ARTIFACT_ID=books
14 | POM_VERSION=1.2
15 | POM_NAME=android-books
16 | POM_PACKAGING=pom
17 | POM_DESCRIPTION=android-books
18 | POM_URL=https://github.com/snowdream/android-books
19 | POM_INCEPTION_YEAR=2014
20 |
21 | POM_SCM_URL=git@github.com:snowdream/android-books.git
22 | POM_SCM_CONNECTION=scm:git:git@github.com:snowdream/android-books.git
23 | POM_SCM_DEV_CONNECTION=scm:git:git@github.com:snowdream/android-books.git
24 |
25 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
26 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
27 | POM_LICENCE_DIST=repo
28 | POM_LICENCE_COMMENTS=A business-friendly OSS license
29 |
30 | POM_DEVELOPER_ID=snowdream
31 | POM_DEVELOPER_NAME=YangHui
32 | POM_DEVELOPER_EMAIL=yanghui1986527@gmail.com
33 | POM_DEVELOPER_URL=http://snowdream.github.io
34 |
35 | POM_ISSUE_MANAGEMENT_SYSTEM=Github
36 | POM_ISSUE_MANAGEMENT_URL=https://github.com/snowdream/android-books/issues
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by http://gitignore.io
2 |
3 | ### Windows ###
4 | # Windows image file caches
5 | Thumbs.db
6 | ehthumbs.db
7 |
8 | # Folder config file
9 | Desktop.ini
10 |
11 | # Recycle Bin used on file shares
12 | $RECYCLE.BIN/
13 |
14 | ### Linux ###
15 | .*
16 | !.gitignore
17 | !.git*
18 | *~
19 |
20 |
21 | ### Eclipse ###
22 | *.pydevproject
23 | .project
24 | .metadata
25 | bin/**
26 | tmp/**
27 | tmp/**/*
28 | *.tmp
29 | *.bak
30 | *.swp
31 | *~.nib
32 | local.properties
33 | .classpath
34 | .settings/
35 | .loadpath
36 |
37 | # External tool builders
38 | .externalToolBuilders/
39 |
40 | # Locally stored "Eclipse launch configurations"
41 | *.launch
42 |
43 | # CDT-specific
44 | .cproject
45 |
46 | # PDT-specific
47 | .buildpath
48 |
49 | ### Android ###
50 | # built application files
51 | *.apk
52 | *.ap_
53 |
54 | # files for the dex VM
55 | *.dex
56 |
57 | # Java class files
58 | *.class
59 |
60 | # generated files
61 | bin/
62 | gen/
63 |
64 | # Local configuration file (sdk path, etc)
65 | local.properties
66 |
67 | # Eclipse project files
68 | .classpath
69 | .project
70 |
71 | # Proguard folder generated by Eclipse
72 | proguard/
73 |
74 | # Proguard folder generated by Intellij
75 | proguard_logs/
76 |
77 | # Intellij project files
78 | *.iml
79 | *.ipr
80 | *.iws
81 | .idea/
82 |
83 | adt-bundle-windows-x86_64/
84 |
85 | ### Gradle ###
86 | # Exclude Folder List #
87 | .gradle/
88 | build/
89 |
90 | ### Maven ###
91 | target/
92 |
93 | ### Java ###
94 | *.class
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
24 |
25 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
20 |
21 |
26 |
27 |
28 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main_blacktoolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
18 |
19 |
24 |
25 |
26 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_subject_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
20 |
25 |
32 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/entity/BookItem.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books.entity;
2 |
3 | import org.parceler.Parcel;
4 |
5 | /**
6 | * Created by hui.yang on 2015/1/24.
7 | */
8 | @Parcel(Parcel.Serialization.METHOD)
9 | public class BookItem {
10 | private String language = null;
11 | private String country = null;
12 | private String author = null;
13 | private String title = null;
14 | private String desc = null;
15 | private boolean isDefault = false;
16 | private String url = null;
17 | private String img = null;
18 |
19 | public String getLanguage() {
20 | return language;
21 | }
22 |
23 | public void setLanguage(String language) {
24 | this.language = language;
25 | }
26 |
27 | public String getCountry() {
28 | return country;
29 | }
30 |
31 | public void setCountry(String country) {
32 | this.country = country;
33 | }
34 |
35 | public String getAuthor() {
36 | return author;
37 | }
38 |
39 | public void setAuthor(String author) {
40 | this.author = author;
41 | }
42 |
43 | public String getTitle() {
44 | return title;
45 | }
46 |
47 | public void setTitle(String title) {
48 | this.title = title;
49 | }
50 |
51 | public String getDesc() {
52 | return desc;
53 | }
54 |
55 | public void setDesc(String desc) {
56 | this.desc = desc;
57 | }
58 |
59 | public boolean isDefault() {
60 | return isDefault;
61 | }
62 |
63 | public void setDefault(boolean isDefault) {
64 | this.isDefault = isDefault;
65 | }
66 |
67 | public String getUrl() {
68 | return url;
69 | }
70 |
71 | public void setUrl(String url) {
72 | this.url = url;
73 | }
74 |
75 | public String getImg() {
76 | return img;
77 | }
78 |
79 | public void setImg(String img) {
80 | this.img = img;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/entity/Subject.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books.entity;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.util.Locale;
6 |
7 | /**
8 | * Created by hui.yang on 2015/1/24.
9 | */
10 | public class Subject {
11 | private String zh_name = null;
12 | private String en_name = null;
13 | /**
14 | * for example, ANT000000 as a key for Antiques & Collectibles
15 | */
16 | private String key = null;
17 | private String url = null;
18 | private String language = null;
19 |
20 | private Subject(){
21 | };
22 |
23 | public Subject(String key, String en_name, String zh_name,String url){
24 | this.key = key;
25 | this.en_name = en_name;
26 | this.zh_name = zh_name;
27 | this.url = url;
28 |
29 | language = Locale.getDefault().getLanguage();
30 | }
31 |
32 | /**
33 | * Whether the subject is valid.
34 | *
35 | * @return
36 | */
37 | public boolean isValid() {
38 | return !TextUtils.isEmpty(key) && !TextUtils.isEmpty(en_name) && !TextUtils.isEmpty(url);
39 | }
40 |
41 | public String getZh_name() {
42 | return zh_name;
43 | }
44 |
45 | public void setZh_name(String zh_name) {
46 | this.zh_name = zh_name;
47 | }
48 |
49 | public String getEn_name() {
50 | return en_name;
51 | }
52 |
53 | public void setEn_name(String en_name) {
54 | this.en_name = en_name;
55 | }
56 |
57 | public String getName() {
58 | if (language.equalsIgnoreCase("zh")){
59 | return getZh_name();
60 | }else{
61 | return getEn_name();
62 | }
63 | }
64 |
65 | public String getKey() {
66 | return key;
67 | }
68 |
69 | public void setKey(String key) {
70 | this.key = key;
71 | }
72 |
73 | public String getUrl() {
74 | return url;
75 | }
76 |
77 | public void setUrl(String url) {
78 | this.url = url;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #android-books
2 |
3 | ##Introduction
4 | android app - books
5 | android books from github or other websites.
6 |
7 | ##System requirements
8 | Android 2.3+
9 |
10 | ##Download
11 | Google Play : [][1]
12 | Github : [https://github.com/snowdream/android-books/releases/download/v1.2/books-v1.2-release.apk][2]
13 |
14 | ##Preview
15 | [](https://play.google.com/store/apps/details?id=com.github.snowdream.android.apps.books)
16 | [](https://play.google.com/store/apps/details?id=com.github.snowdream.android.apps.books)
17 | [](https://play.google.com/store/apps/details?id=com.github.snowdream.android.apps.books)
18 | [](https://play.google.com/store/apps/details?id=com.github.snowdream.android.apps.books)
19 |
20 | ##License
21 | ```
22 | Copyright (C) 2014 Snowdream Mobile
23 |
24 | Licensed under the Apache License, Version 2.0 (the "License");
25 | you may not use this file except in compliance with the License.
26 | You may obtain a copy of the License at
27 |
28 | http://www.apache.org/licenses/LICENSE-2.0
29 |
30 | Unless required by applicable law or agreed to in writing, software
31 | distributed under the License is distributed on an "AS IS" BASIS,
32 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 | See the License for the specific language governing permissions and
34 | limitations under the License.
35 | ```
36 |
37 | [1]:https://play.google.com/store/apps/details?id=com.github.snowdream.android.apps.books
38 | [2]:https://github.com/snowdream/android-books/releases/download/v1.2/books-v1.2-release.apk
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main_topdrawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
20 |
24 |
25 |
30 |
31 |
36 |
37 |
38 |
39 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
22 |
23 |
24 |
25 |
28 |
29 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
47 |
48 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/config/android-library.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'android-library'
2 |
3 | archivesBaseName = POM_NAME
4 |
5 | dependencies {
6 | }
7 |
8 | android {
9 | compileSdkVersion Integer.parseInt(project.COMPILE_SDK_VERSION)
10 | buildToolsVersion project.BUILD_TOOLS_VERSION
11 |
12 | defaultConfig {
13 | versionCode Integer.parseInt(project.VERSION_CODE)
14 | versionName project.VERSION_NAME
15 | minSdkVersion Integer.parseInt(project.MIN_SDK_VERSION)
16 | targetSdkVersion Integer.parseInt(project.TARGET_SDK_VERSION)
17 |
18 | testApplicationId project.PACKAGE_NAME+".test"
19 | testInstrumentationRunner "android.test.InstrumentationTestRunner"
20 | testHandleProfiling true
21 | testFunctionalTest true
22 | }
23 |
24 | buildTypes {
25 | release {
26 | minifyEnabled true
27 | shrinkResources true
28 | proguardFiles getDefaultProguardFile('proguard-android-lib-optimize.txt'), 'proguard-rules.txt'
29 | //signingConfig signingConfigs.release
30 | }
31 | }
32 |
33 | packagingOptions {
34 | exclude 'META-INF/DEPENDENCIES'
35 | exclude 'META-INF/NOTICE'
36 | exclude 'META-INF/LICENSE'
37 | exclude 'META-INF/LICENSE.txt'
38 | exclude 'META-INF/NOTICE.txt'
39 | }
40 |
41 | lintOptions {
42 | abortOnError false
43 | }
44 | }
45 |
46 | android.libraryVariants.all { variant ->
47 |
48 | task("generate${variant.name}Javadoc", type: Javadoc) {
49 | title = "android lib - $POM_NAME $version API"
50 | description "Generates Javadoc for $variant.name."
51 | source = variant.javaCompile.source
52 | ext.androidJar =
53 | "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
54 | classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar)
55 | options {
56 | locale = 'en_US'
57 | encoding = 'UTF-8'
58 | charSet = 'UTF-8'
59 | links("http://docs.oracle.com/javase/7/docs/api/");
60 | linksOffline("http://d.android.com/reference", "${android.sdkDirectory}/docs/reference");
61 | links("http://ormlite.com/javadoc/ormlite-core/");
62 | links("http://ormlite.com/javadoc/ormlite-android/");
63 | }
64 | exclude '**/BuildConfig.java'
65 | exclude '**/R.java'
66 | exclude '**/Log2File.java'
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/SubjectFragment.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.text.TextUtils;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.AdapterView;
10 | import android.widget.ListView;
11 | import com.github.snowdream.android.app.books.entity.Book;
12 | import org.parceler.Parcels;
13 |
14 | import java.util.List;
15 | import java.util.Locale;
16 |
17 | /**
18 | * Created by hui.yang on 2015/1/24.
19 | */
20 | public class SubjectFragment extends Fragment implements AdapterView.OnItemClickListener {
21 | public static final String KEY_SUBJECT_BOOKS = "key_subject_books";
22 |
23 | private ListView listview = null;
24 | private String language = null;
25 |
26 |
27 | @Override
28 | public void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | }
31 |
32 | @Override
33 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
34 | return inflater.inflate(R.layout.fragment_subject, null);
35 | }
36 |
37 | @Override
38 | public void onViewCreated(View view, Bundle savedInstanceState) {
39 | super.onViewCreated(view, savedInstanceState);
40 |
41 | initView(view);
42 | initData();
43 | }
44 |
45 | private void initView(View rootview) {
46 | listview = (ListView) rootview.findViewById(R.id.listview);
47 | listview.setOnItemClickListener(this);
48 | }
49 |
50 |
51 | private void initData() {
52 | language = Locale.getDefault().getLanguage();
53 |
54 | Bundle bundle = getArguments();
55 |
56 | List books = Parcels.unwrap(bundle.getParcelable(SubjectFragment.KEY_SUBJECT_BOOKS)) ;
57 | if (books != null && !books.isEmpty()){
58 | SubjectAdapter adapter = new SubjectAdapter(getActivity(),books);
59 | listview.setAdapter(adapter);
60 | }
61 | }
62 |
63 | @Override
64 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
65 |
66 | SubjectAdapter adapter = (SubjectAdapter) listview.getAdapter();
67 |
68 | Book book = adapter.getItem(position);
69 | if (book != null && !TextUtils.isEmpty(book.getUrl(language))){
70 | BookFragment fragment = new BookFragment();
71 |
72 | Bundle bundle = new Bundle();
73 | bundle.putString(BookFragment.BOOK_URL_KEY,book.getUrl(language));
74 |
75 | fragment.setArguments(bundle);
76 |
77 | getActivity().getSupportFragmentManager().beginTransaction().add(R.id.container,fragment).addToBackStack(null).commit();
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/config/android.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'android'
2 |
3 | dependencies {
4 | }
5 |
6 | android {
7 | compileSdkVersion Integer.parseInt(project.COMPILE_SDK_VERSION)
8 | buildToolsVersion project.BUILD_TOOLS_VERSION
9 |
10 | defaultConfig {
11 | versionCode Integer.parseInt(project.VERSION_CODE)
12 | versionName project.VERSION_NAME
13 | minSdkVersion Integer.parseInt(project.MIN_SDK_VERSION)
14 | targetSdkVersion Integer.parseInt(project.TARGET_SDK_VERSION)
15 | applicationId project.PACKAGE_NAME
16 |
17 | testApplicationId project.PACKAGE_NAME+".test"
18 | testInstrumentationRunner "android.test.InstrumentationTestRunner"
19 | testHandleProfiling true
20 | testFunctionalTest true
21 | }
22 |
23 | signingConfigs {
24 | release {
25 | storeFile file(System.getenv("KEYSTORE"))
26 | storePassword System.getenv("KEYSTORE_PASSWORD")
27 | keyAlias System.getenv("KEY_ALIAS")
28 | keyPassword System.getenv("KEY_PASSWORD")
29 | }
30 | }
31 |
32 | buildTypes {
33 | release {
34 | minifyEnabled true
35 | shrinkResources true
36 | proguardFiles getDefaultProguardFile('proguard-android-app-optimize.txt'), 'proguard-rules.txt'
37 | signingConfig signingConfigs.release
38 | }
39 | }
40 |
41 | packagingOptions {
42 | exclude 'META-INF/DEPENDENCIES'
43 | exclude 'META-INF/NOTICE'
44 | exclude 'META-INF/LICENSE'
45 | exclude 'META-INF/LICENSE.txt'
46 | exclude 'META-INF/NOTICE.txt'
47 | }
48 |
49 | lintOptions {
50 | abortOnError false
51 | }
52 | }
53 |
54 | android.applicationVariants.all { variant ->
55 | def apk = variant.outputs[0].outputFile;
56 | def newName = "";
57 |
58 | newName = apk.name.replace(project.name, POM_NAME + "-v" + android.defaultConfig.versionName);
59 | newName = newName.replace("-" + variant.buildType.name, "");
60 | newName = newName.replace(".apk", "-" + variant.buildType.name.toLowerCase() + ".apk");
61 |
62 | variant.outputs[0].outputFile = new File(apk.parentFile, newName);
63 | if (variant.outputs[0].zipAlign) {
64 | variant.outputs[0].zipAlign.outputFile = new File(apk.parentFile, newName.replace("-unaligned", ""));
65 | }
66 | }
67 |
68 | android.applicationVariants.all { variant ->
69 |
70 | task("generate${variant.name}Javadoc", type: Javadoc) {
71 | title = "android lib - $POM_NAME $version API"
72 | description "Generates Javadoc for $variant.name."
73 | source = variant.javaCompile.source
74 | ext.androidJar =
75 | "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
76 | classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar)
77 | options {
78 | locale = 'en_US'
79 | encoding = 'UTF-8'
80 | charSet = 'UTF-8'
81 | links("http://docs.oracle.com/javase/7/docs/api/");
82 | linksOffline("http://d.android.com/reference", "${android.sdkDirectory}/docs/reference");
83 | }
84 | exclude '**/BuildConfig.java'
85 | exclude '**/R.java'
86 | exclude '**/Log2File.java'
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/MainApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Snowdream Mobile
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.snowdream.android.app.books;
18 |
19 | import android.app.Application;
20 | import android.content.Context;
21 | import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
22 | import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
23 | import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
24 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
25 | import com.nostra13.universalimageloader.core.ImageLoader;
26 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
27 | import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
28 | import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
29 | import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
30 | import com.nostra13.universalimageloader.utils.StorageUtils;
31 |
32 | import java.io.File;
33 |
34 | /**
35 | * Created by hui.yang on 2014/12/14.
36 | */
37 | public class MainApplication extends Application {
38 |
39 | @Override
40 | public void onCreate() {
41 | super.onCreate();
42 |
43 | //init image loader
44 | initImageLoader();
45 | }
46 |
47 | private void initImageLoader(){
48 | Context context = getApplicationContext();
49 | File cacheDir = StorageUtils.getCacheDirectory(context);
50 | ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
51 | .memoryCacheExtraOptions(480, 800) // default = device screen dimensions
52 | .diskCacheExtraOptions(480, 800, null)
53 | .threadPriority(Thread.NORM_PRIORITY - 2) // default
54 | .tasksProcessingOrder(QueueProcessingType.FIFO) // default
55 | .denyCacheImageMultipleSizesInMemory()
56 | .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
57 | .memoryCacheSize(2 * 1024 * 1024)
58 | .memoryCacheSizePercentage(13) // default
59 | .diskCache(new UnlimitedDiscCache(cacheDir)) // default
60 | .diskCacheSize(50 * 1024 * 1024)
61 | .diskCacheFileCount(100)
62 | .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
63 | .imageDownloader(new BaseImageDownloader(context)) // default
64 | .imageDecoder(new BaseImageDecoder(false)) // default
65 | .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
66 | // .writeDebugLogs()
67 | .build();
68 |
69 | ImageLoader.getInstance().init(config);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/SubjectAdapter.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books;
2 |
3 | import android.app.Service;
4 | import android.content.Context;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.BaseAdapter;
9 | import android.widget.ImageView;
10 | import android.widget.TextView;
11 | import com.github.snowdream.android.app.books.entity.Book;
12 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
13 | import com.nostra13.universalimageloader.core.ImageLoader;
14 | import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
15 |
16 | import java.util.List;
17 | import java.util.Locale;
18 |
19 | /**
20 | * Created by hui.yang on 2015/1/24.
21 | */
22 | public class SubjectAdapter extends BaseAdapter {
23 | private Context context = null;
24 | private List list = null;
25 | private LayoutInflater inflater = null;
26 | private String language = null;
27 | DisplayImageOptions options = null;
28 |
29 | private SubjectAdapter(){}
30 |
31 | public SubjectAdapter(Context context, List list) {
32 | this.context = context;
33 | this.list = list;
34 | inflater = (LayoutInflater) context.getSystemService(Service.LAYOUT_INFLATER_SERVICE);
35 |
36 | language = Locale.getDefault().getLanguage();
37 |
38 | options = new DisplayImageOptions.Builder()
39 | .showImageOnLoading(R.drawable.ic_book)
40 | .showImageForEmptyUri(R.drawable.ic_book)
41 | .showImageOnFail(R.drawable.ic_book)
42 | .displayer(new FadeInBitmapDisplayer(500))
43 | .build();
44 |
45 | }
46 |
47 | @Override
48 | public int getCount() {
49 | if (list != null && !list.isEmpty()){
50 | return list.size();
51 | }
52 |
53 | return 0;
54 | }
55 |
56 | @Override
57 | public Book getItem(int position) {
58 | if (position >= 0 && position < getCount()){
59 | return list.get(position);
60 | }
61 | return null;
62 | }
63 |
64 | @Override
65 | public long getItemId(int position) {
66 | return position;
67 | }
68 |
69 | @Override
70 | public View getView(int position, View convertView, ViewGroup parent) {
71 | ViewHolder holder = null;
72 | if (convertView == null){
73 | holder = new ViewHolder();
74 |
75 | convertView = inflater.inflate(
76 | R.layout.fragment_subject_item, null);
77 | holder.imageView = (ImageView)convertView.findViewById(R.id.image);
78 | holder.title = (TextView)convertView.findViewById(R.id.title);
79 | holder.subtitle = (TextView)convertView.findViewById(R.id.subtitle);
80 |
81 | convertView.setTag(holder);
82 | }else{
83 | holder = (ViewHolder) convertView.getTag();
84 | }
85 |
86 | Book book = getItem(position);
87 | if (book != null){
88 | holder.title.setText(book.getTitle(language));
89 | holder.subtitle.setText(book.getDesc(language));
90 | ImageLoader.getInstance().displayImage(book.getImg(language), holder.imageView,options);
91 | }
92 |
93 | return convertView;
94 | }
95 |
96 | public final class ViewHolder {
97 | ImageView imageView;
98 | TextView title;
99 | TextView subtitle;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/docs/test/computer.json:
--------------------------------------------------------------------------------
1 | {
2 | "books": [
3 | {
4 | "book": [
5 | {
6 | "language": "zh",
7 | "country": "TW",
8 | "author": "wcc723",
9 | "title": "Google Material Design 正體中文版",
10 | "desc": "Google Material Design 正體中文版",
11 | "default": true,
12 | "url": "http://wcc723.gitbooks.io/google_design_translate/content/",
13 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/wcc723/google_design_translate.jpg?build=1420620075081&v=6.3.3"
14 | }
15 | ]
16 | },
17 | {
18 | "book": [
19 | {
20 | "language": "zh",
21 | "country": "CN",
22 | "author": "DONG , Yucheng Wang and Avatar Qing",
23 | "title": "Gradle User Guide 中文版",
24 | "desc": "Gradle User Guide 中文版",
25 | "default": true,
26 | "url": "https://www.gitbook.com/read/book/dongchuan/gradle-user-guide-",
27 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/dongchuan/gradle-user-guide-.jpg?build=1422006788753&v=6.3.3"
28 | }
29 | ]
30 | },
31 | {
32 | "book": [
33 | {
34 | "language": "zh",
35 | "country": "CN",
36 | "author": "Open Source Geek",
37 | "title": "Puppet运维实战",
38 | "desc": "备受IT运维人员青睐的自动化运维实战",
39 | "default": true,
40 | "url": "https://www.gitbook.com/read/book/kisspuppet/puppet",
41 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kisspuppet/puppet.jpg?build=1419923407319&v=6.3.3"
42 | }
43 | ]
44 | },
45 | {
46 | "book": [
47 | {
48 | "language": "en",
49 | "country": "US",
50 | "author": "kennel209",
51 | "title": "Owasp Testing Guide v4",
52 | "desc": "Just A GITBOOK Ver of WIKI. Now translating to Chinese.",
53 | "default": true,
54 | "url": "http://kennel209.gitbooks.io/owasp-testing-guide-v4/content/",
55 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kennel209/owasp-testing-guide-v4.jpg?build=1416745888693&v=6.3.3"
56 | },
57 | {
58 | "language": "zh",
59 | "country": "CN",
60 | "author": "kennel209",
61 | "title": "OWASP 测试指南 4.0",
62 | "desc": "OWASP 的宗旨:技术的开放与协作",
63 | "default": true,
64 | "url": "http://kennel209.gitbooks.io/owasp-testing-guide-v4/content/",
65 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kennel209/owasp-testing-guide-v4.jpg?build=1416745888693&v=6.3.3"
66 | }
67 | ]
68 | },
69 | {
70 | "book": [
71 | {
72 | "language": "zh",
73 | "country": "TW",
74 | "author": "Open Source Geek",
75 | "title": "物件導向軟體工程",
76 | "desc": "這是專為逢甲資工 OOSE 課程設計的講義。",
77 | "default": true,
78 | "url": "https://www.gitbook.com/read/book/nlhsueh/oose",
79 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/nlhsueh/oose.jpg?build=1420295795402&v=6.3.3"
80 | }
81 | ]
82 | }
83 | ]
84 | }
--------------------------------------------------------------------------------
/docs/test/education.json:
--------------------------------------------------------------------------------
1 | {
2 | "books": [
3 | {
4 | "book": [
5 | {
6 | "language": "zh",
7 | "country": "TW",
8 | "author": "Open Source Geek",
9 | "title": "物件導向軟體工程",
10 | "desc": "這是專為逢甲資工 OOSE 課程設計的講義。",
11 | "default": true,
12 | "url": "https://www.gitbook.com/read/book/nlhsueh/oose",
13 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/nlhsueh/oose.jpg?build=1420295795402&v=6.3.3"
14 | }
15 | ]
16 | },
17 | {
18 | "book": [
19 | {
20 | "language": "en",
21 | "country": "US",
22 | "author": "kennel209",
23 | "title": "Owasp Testing Guide v4",
24 | "desc": "Just A GITBOOK Ver of WIKI. Now translating to Chinese.",
25 | "default": true,
26 | "url": "http://kennel209.gitbooks.io/owasp-testing-guide-v4/content/",
27 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kennel209/owasp-testing-guide-v4.jpg?build=1416745888693&v=6.3.3"
28 | },
29 | {
30 | "language": "zh",
31 | "country": "CN",
32 | "author": "kennel209",
33 | "title": "OWASP 测试指南 4.0",
34 | "desc": "OWASP 的宗旨:技术的开放与协作",
35 | "default": true,
36 | "url": "http://kennel209.gitbooks.io/owasp-testing-guide-v4/content/",
37 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kennel209/owasp-testing-guide-v4.jpg?build=1416745888693&v=6.3.3"
38 | }
39 | ]
40 | },
41 | {
42 | "book": [
43 | {
44 | "language": "zh",
45 | "country": "TW",
46 | "author": "wcc723",
47 | "title": "Google Material Design 正體中文版",
48 | "desc": "Google Material Design 正體中文版",
49 | "default": true,
50 | "url": "http://wcc723.gitbooks.io/google_design_translate/content/",
51 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/wcc723/google_design_translate.jpg?build=1420620075081&v=6.3.3"
52 | }
53 | ]
54 | },
55 | {
56 | "book": [
57 | {
58 | "language": "en",
59 | "country": "US",
60 | "author": "LarryLo",
61 | "title": "Distribute Cloud Environment on Ubuntu 14.04 with Docker",
62 | "desc": "Distribute Cloud Environment on Ubuntu 14.04 with Docker",
63 | "default": true,
64 | "url": "https://www.gitbook.com/read/book/larrylo/distribute-cloud-environment-on-ubuntu-14-04-with",
65 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/larrylo/distribute-cloud-environment-on-ubuntu-14-04-with.jpg?build=1421723836698&v=6.3.3"
66 | }
67 | ]
68 | },
69 | {
70 | "book": [
71 | {
72 | "language": "zh",
73 | "country": "CN",
74 | "author": "Open Source Geek",
75 | "title": "Puppet运维实战",
76 | "desc": "备受IT运维人员青睐的自动化运维实战",
77 | "default": true,
78 | "url": "https://www.gitbook.com/read/book/kisspuppet/puppet",
79 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kisspuppet/puppet.jpg?build=1419923407319&v=6.3.3"
80 | }
81 | ]
82 | }
83 | ]
84 | }
--------------------------------------------------------------------------------
/docs/test/foreign.json:
--------------------------------------------------------------------------------
1 | {
2 | "books": [
3 | {
4 | "book": [
5 | {
6 | "language": "zh",
7 | "country": "TW",
8 | "author": "XBadaBing",
9 | "title": "導遊、領隊FUN英語(mp3) “The Whole Package”",
10 | "desc": "導遊、領隊FUN英語(mp3) “The Whole Package”",
11 | "default": true,
12 | "url": "https://www.gitbook.com/read/book/michaelchen/test",
13 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/michaelchen/test.jpg?build=1421878828655&v=6.3.3"
14 | }
15 | ]
16 | },
17 | {
18 | "book": [
19 | {
20 | "language": "en",
21 | "country": "US",
22 | "author": "kennel209",
23 | "title": "Owasp Testing Guide v4",
24 | "desc": "Just A GITBOOK Ver of WIKI. Now translating to Chinese.",
25 | "default": true,
26 | "url": "http://kennel209.gitbooks.io/owasp-testing-guide-v4/content/",
27 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kennel209/owasp-testing-guide-v4.jpg?build=1416745888693&v=6.3.3"
28 | },
29 | {
30 | "language": "zh",
31 | "country": "CN",
32 | "author": "kennel209",
33 | "title": "OWASP 测试指南 4.0",
34 | "desc": "OWASP 的宗旨:技术的开放与协作",
35 | "default": true,
36 | "url": "http://kennel209.gitbooks.io/owasp-testing-guide-v4/content/",
37 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kennel209/owasp-testing-guide-v4.jpg?build=1416745888693&v=6.3.3"
38 | }
39 | ]
40 | },
41 | {
42 | "book": [
43 | {
44 | "language": "zh",
45 | "country": "TW",
46 | "author": "wcc723",
47 | "title": "Google Material Design 正體中文版",
48 | "desc": "Google Material Design 正體中文版",
49 | "default": true,
50 | "url": "http://wcc723.gitbooks.io/google_design_translate/content/",
51 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/wcc723/google_design_translate.jpg?build=1420620075081&v=6.3.3"
52 | }
53 | ]
54 | },
55 | {
56 | "book": [
57 | {
58 | "language": "en",
59 | "country": "US",
60 | "author": "LarryLo",
61 | "title": "Distribute Cloud Environment on Ubuntu 14.04 with Docker",
62 | "desc": "Distribute Cloud Environment on Ubuntu 14.04 with Docker",
63 | "default": true,
64 | "url": "https://www.gitbook.com/read/book/larrylo/distribute-cloud-environment-on-ubuntu-14-04-with",
65 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/larrylo/distribute-cloud-environment-on-ubuntu-14-04-with.jpg?build=1421723836698&v=6.3.3"
66 | }
67 | ]
68 | },
69 | {
70 | "book": [
71 | {
72 | "language": "zh",
73 | "country": "CN",
74 | "author": "Open Source Geek",
75 | "title": "Puppet运维实战",
76 | "desc": "备受IT运维人员青睐的自动化运维实战",
77 | "default": true,
78 | "url": "https://www.gitbook.com/read/book/kisspuppet/puppet",
79 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/kisspuppet/puppet.jpg?build=1419923407319&v=6.3.3"
80 | }
81 | ]
82 | }
83 | ]
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v4.widget.DrawerLayout;
7 | import android.support.v7.app.ActionBarActivity;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.Menu;
10 | import android.widget.Toast;
11 | import com.github.snowdream.android.app.books.controller.BookManager;
12 | import com.github.snowdream.android.app.books.controller.CallBack;
13 | import com.github.snowdream.android.app.books.entity.Book;
14 | import com.github.snowdream.android.app.books.entity.Subject;
15 | import com.github.snowdream.android.util.Log;
16 | import org.parceler.Parcels;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 |
22 | public class MainActivity extends ActionBarActivity implements NavigationDrawerCallbacks {
23 |
24 | private Toolbar mToolbar;
25 | private NavigationDrawerFragment mNavigationDrawerFragment;
26 | private List items;
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_main);
31 | mToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
32 | setSupportActionBar(mToolbar);
33 | getSupportActionBar().setDisplayShowHomeEnabled(true);
34 |
35 | mNavigationDrawerFragment = (NavigationDrawerFragment)getSupportFragmentManager().findFragmentById(R.id.fragment_drawer);
36 | mNavigationDrawerFragment.setup(R.id.fragment_drawer, (DrawerLayout) findViewById(R.id.drawer), mToolbar);
37 |
38 | items = new ArrayList();
39 | items.add(new NavigationItem(new Subject("REC000000","Recommend","推荐","https://raw.githubusercontent.com/snowdream/android-books/master/docs/test/recomend.json"), getResources().getDrawable(R.drawable.ic_menu_check)));
40 | items.add(new NavigationItem(new Subject("COM000000","Computers","计算机技术","https://raw.githubusercontent.com/snowdream/android-books/master/docs/test/computer.json"), getResources().getDrawable(R.drawable.ic_menu_check)));
41 | items.add(new NavigationItem(new Subject("FOR000000","Foreign Language Study","外语学习","https://raw.githubusercontent.com/snowdream/android-books/master/docs/test/foreign.json"), getResources().getDrawable(R.drawable.ic_menu_check)));
42 | items.add(new NavigationItem(new Subject("EDU000000","Education","教育","https://raw.githubusercontent.com/snowdream/android-books/master/docs/test/education.json"), getResources().getDrawable(R.drawable.ic_menu_check)));
43 |
44 | mNavigationDrawerFragment.setMenu(items);
45 | mNavigationDrawerFragment.refresh();
46 | }
47 |
48 | @Override
49 | public boolean onCreateOptionsMenu(Menu menu) {
50 | //getMenuInflater().inflate(R.menu.main, menu);
51 | return super.onCreateOptionsMenu(menu);
52 | }
53 |
54 | @Override
55 | public void onNavigationDrawerItemSelected(int position) {
56 | NavigationItem item = items.get(position);
57 | Subject subject = item.getSubject();
58 |
59 | BookManager.getBooks(subject.getUrl(), new CallBack>() {
60 | @Override
61 | public void callback(List books) {
62 | Log.i(books.toString());
63 | if (books != null && !books.isEmpty()) {
64 | SubjectFragment fragment = new SubjectFragment();
65 |
66 | Bundle bundle = new Bundle();
67 | bundle.putParcelable(SubjectFragment.KEY_SUBJECT_BOOKS, Parcels.wrap(books));
68 | fragment.setArguments(bundle);
69 | getSupportFragmentManager().getFragments().size();
70 |
71 | List list = getSupportFragmentManager().getFragments();
72 | if (list == null || list.isEmpty()){
73 | getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).commit();
74 | }else {
75 | getSupportFragmentManager().beginTransaction().add(R.id.container, fragment).addToBackStack(null).commit();
76 | }
77 | }
78 | }
79 | });
80 | }
81 |
82 | @Override
83 | public void onBackPressed() {
84 | if (mNavigationDrawerFragment.isDrawerOpen())
85 | mNavigationDrawerFragment.closeDrawer();
86 | else
87 | super.onBackPressed();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/ScrimInsetsFrameLayout.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.support.v4.view.ViewCompat;
9 | import android.util.AttributeSet;
10 | import android.widget.FrameLayout;
11 |
12 |
13 | /**
14 | * A layout that draws something in the insets passed to {@link #fitSystemWindows(Rect)}, i.e. the area above UI chrome
15 | * (status and navigation bars, overlay action bars).
16 | */
17 | public class ScrimInsetsFrameLayout extends FrameLayout {
18 | private Drawable mInsetForeground;
19 |
20 | private Rect mInsets;
21 | private Rect mTempRect = new Rect();
22 | private OnInsetsCallback mOnInsetsCallback;
23 |
24 | public ScrimInsetsFrameLayout(Context context) {
25 | super(context);
26 | init(context, null, 0);
27 | }
28 |
29 | public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) {
30 | super(context, attrs);
31 | init(context, attrs, 0);
32 | }
33 |
34 | public ScrimInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {
35 | super(context, attrs, defStyle);
36 | init(context, attrs, defStyle);
37 | }
38 |
39 | private void init(Context context, AttributeSet attrs, int defStyle) {
40 | final TypedArray a = context.obtainStyledAttributes(attrs,
41 | R.styleable.ScrimInsetsView, defStyle, 0);
42 | if (a == null) {
43 | return;
44 | }
45 | mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsView_insetForeground);
46 | a.recycle();
47 |
48 | setWillNotDraw(true);
49 | }
50 |
51 | @Override
52 | protected boolean fitSystemWindows(Rect insets) {
53 | mInsets = new Rect(insets);
54 | setWillNotDraw(mInsetForeground == null);
55 | ViewCompat.postInvalidateOnAnimation(this);
56 | if (mOnInsetsCallback != null) {
57 | mOnInsetsCallback.onInsetsChanged(insets);
58 | }
59 | return true; // consume insets
60 | }
61 |
62 | @Override
63 | public void draw(Canvas canvas) {
64 | super.draw(canvas);
65 |
66 | int width = getWidth();
67 | int height = getHeight();
68 | if (mInsets != null && mInsetForeground != null) {
69 | int sc = canvas.save();
70 | canvas.translate(getScrollX(), getScrollY());
71 |
72 | // Top
73 | mTempRect.set(0, 0, width, mInsets.top);
74 | mInsetForeground.setBounds(mTempRect);
75 | mInsetForeground.draw(canvas);
76 |
77 | // Bottom
78 | mTempRect.set(0, height - mInsets.bottom, width, height);
79 | mInsetForeground.setBounds(mTempRect);
80 | mInsetForeground.draw(canvas);
81 |
82 | // Left
83 | mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom);
84 | mInsetForeground.setBounds(mTempRect);
85 | mInsetForeground.draw(canvas);
86 |
87 | // Right
88 | mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom);
89 | mInsetForeground.setBounds(mTempRect);
90 | mInsetForeground.draw(canvas);
91 |
92 | canvas.restoreToCount(sc);
93 | }
94 | }
95 |
96 | @Override
97 | protected void onAttachedToWindow() {
98 | super.onAttachedToWindow();
99 | if (mInsetForeground != null) {
100 | mInsetForeground.setCallback(this);
101 | }
102 | }
103 |
104 | @Override
105 | protected void onDetachedFromWindow() {
106 | super.onDetachedFromWindow();
107 | if (mInsetForeground != null) {
108 | mInsetForeground.setCallback(null);
109 | }
110 | }
111 |
112 | /**
113 | * Allows the calling container to specify a callback for custom processing when insets change (i.e. when
114 | * {@link #fitSystemWindows(Rect)} is called. This is useful for setting padding on UI elements based on
115 | * UI chrome insets (e.g. a Google Map or a ListView). When using with ListView or GridView, remember to set
116 | * clipToPadding to false.
117 | */
118 | public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) {
119 | mOnInsetsCallback = onInsetsCallback;
120 | }
121 |
122 | public static interface OnInsetsCallback {
123 | public void onInsetsChanged(Rect insets);
124 | }
125 | }
--------------------------------------------------------------------------------
/config/maven_push.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven'
2 | apply plugin: 'signing'
3 |
4 | configurations {
5 | archives {
6 | extendsFrom configurations.default
7 | }
8 | }
9 |
10 | def isReleaseBuild() {
11 | return version.contains("SNAPSHOT") == false
12 | }
13 |
14 | def sonatypeRepositoryUrl
15 | if (isReleaseBuild()) {
16 | println 'Sonatype RELEASE BUILD'
17 | sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
18 | } else {
19 | println 'Sonatype SNAPSHOT BUILD'
20 | sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
21 | }
22 |
23 | def githubRepositoryUrl
24 | if (isReleaseBuild()) {
25 | println 'GITHUB RELEASE BUILD'
26 | githubRepositoryUrl = "file:///home/snowdream/workspace/git/mvn-repo/releases"
27 | } else {
28 | println 'GITHUB SNAPSHOT BUILD'
29 | githubRepositoryUrl = "file:///home/snowdream/workspace/git/mvn-repo/snapshots"
30 | }
31 |
32 | if (ext.properties.containsKey('signing.keyId') &&
33 | !ext.properties.containsKey('signing.password')) {
34 | if (System.console()) {
35 | ext.set('signing.password',
36 | System.console().readPassword("\n\$ Type in GPG key password: "))
37 | } else {
38 | ext.set('signing.password', 'snowdream')
39 | }
40 | }
41 |
42 | if (!ext.properties.containsKey('nexusUsername')) {
43 | if (System.console()) {
44 | ext.set('nexusUsername', new String(System.console().readPassword(
45 | "\n\$ Type in username for Sonatype nexus account ${nexusUsername}: ")))
46 | } else {
47 | ext.set('nexusUsername', 'snowdream')
48 | }
49 | }
50 |
51 | if (!ext.properties.containsKey('nexusPassword')) {
52 | if (System.console()) {
53 | ext.set('nexusPassword', new String(System.console().readPassword(
54 | "\n\$ Type in password for Sonatype nexus account ${nexusUsername}: ")))
55 | } else {
56 | ext.set('nexusPassword', 'snowdream')
57 | }
58 | }
59 |
60 | afterEvaluate { project ->
61 | uploadArchives {
62 | repositories {
63 | mavenDeployer {
64 | configurePOM(pom)
65 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
66 |
67 | repository(url: sonatypeRepositoryUrl) {
68 | authentication(userName: nexusUsername, password: nexusPassword)
69 | }
70 | }
71 |
72 | mavenDeployer {
73 | configurePOM(pom)
74 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
75 |
76 | repository(url: githubRepositoryUrl)
77 | }
78 | }
79 | }
80 |
81 | signing {
82 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
83 | sign configurations.archives
84 | }
85 |
86 | task androidReleaseJar(type: Jar, dependsOn: assembleRelease) {
87 | from "$buildDir/intermediates/classes/release/"
88 | exclude '**/BuildConfig.class'
89 | exclude '**/R.class'
90 | exclude '**/R$*.class'
91 | }
92 |
93 | task androidJavadocsJar(type: Jar) {
94 | classifier = 'javadoc'
95 | from "generateReleaseJavadoc.destinationDir"
96 | }
97 |
98 | task androidSourcesJar(type: Jar) {
99 | classifier = 'sources'
100 | from android.sourceSets.main.java.srcDirs
101 | }
102 |
103 |
104 | artifacts {
105 | archives androidReleaseJar
106 | archives androidSourcesJar
107 | archives androidJavadocsJar
108 | }
109 | }
110 |
111 | private configurePOM(def pom) {
112 | pom.project {
113 | groupId POM_GROUP_ID
114 | artifactId POM_ARTIFACT_ID
115 | version POM_VERSION
116 | name POM_NAME
117 | packaging POM_PACKAGING
118 | description POM_DESCRIPTION
119 | url POM_URL
120 | inceptionYear POM_INCEPTION_YEAR
121 |
122 | scm {
123 | url POM_SCM_URL
124 | connection POM_SCM_CONNECTION
125 | developerConnection POM_SCM_DEV_CONNECTION
126 | }
127 |
128 | licenses {
129 | license {
130 | name POM_LICENCE_NAME
131 | url POM_LICENCE_URL
132 | distribution POM_LICENCE_DIST
133 | comments POM_LICENCE_COMMENTS
134 | }
135 | }
136 |
137 | developers {
138 | developer {
139 | id POM_DEVELOPER_ID
140 | name POM_DEVELOPER_NAME
141 | email POM_DEVELOPER_EMAIL
142 | url POM_DEVELOPER_URL
143 | }
144 | }
145 |
146 | issueManagement {
147 | system POM_ISSUE_MANAGEMENT_SYSTEM
148 | url POM_ISSUE_MANAGEMENT_URL
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/controller/BookManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Snowdream Mobile
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.snowdream.android.app.books.controller;
18 |
19 | import android.text.TextUtils;
20 | import com.github.snowdream.android.app.books.entity.Book;
21 | import com.github.snowdream.android.app.books.entity.BookItem;
22 | import com.loopj.android.http.AsyncHttpClient;
23 | import com.loopj.android.http.JsonHttpResponseHandler;
24 | import org.apache.http.Header;
25 | import org.json.JSONArray;
26 | import org.json.JSONException;
27 | import org.json.JSONObject;
28 |
29 | import java.util.ArrayList;
30 | import java.util.List;
31 |
32 | /**
33 | * Created by hui.yang on 2014/12/7.
34 | */
35 | public class BookManager {
36 |
37 | public static void getBooks(final String url, final CallBack callBack) {
38 | List list = null;
39 | if (TextUtils.isEmpty(url)) {
40 | callBack.callback(list);
41 | }
42 |
43 | AsyncHttpClient client = new AsyncHttpClient();
44 | client.get(url, new JsonHttpResponseHandler() {
45 | @Override
46 | public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
47 | List list = parseBooks(response);
48 | if (callBack != null) {
49 | callBack.callback(list);
50 | }
51 | }
52 |
53 | @Override
54 | public void onSuccess(int statusCode, Header[] headers, JSONArray timeline) {
55 | }
56 |
57 | @Override
58 | public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
59 | super.onFailure(statusCode, headers, responseString, throwable);
60 | }
61 | });
62 | }
63 |
64 | /**
65 | * Parse Books
66 | *
67 | * @param obj
68 | * @return
69 | */
70 | private static List parseBooks(JSONObject obj) {
71 | List list = null;
72 |
73 | if (obj == null) {
74 | return list;
75 | }
76 |
77 | try {
78 | list = new ArrayList();
79 | JSONArray booksArray = obj.getJSONArray("books");
80 | int length = booksArray.length();
81 | for (int i = 0; i < length; i++) {
82 | JSONObject oj = booksArray.getJSONObject(i);
83 |
84 | if (oj == null) {
85 | continue;
86 | }
87 |
88 | Book book = new Book();
89 |
90 | List bookItemList = parseBook(oj);
91 |
92 | if (bookItemList != null){
93 | book.setList(bookItemList);
94 | }
95 |
96 | list.add(book);
97 | }
98 | } catch (JSONException e) {
99 | e.printStackTrace();
100 | }
101 |
102 | return list;
103 | }
104 |
105 | /**
106 | * Parse Book
107 | *
108 | * @param obj
109 | * @return
110 | */
111 | private static List parseBook(JSONObject obj) {
112 | List list = null;
113 |
114 | if (obj == null) {
115 | return list;
116 | }
117 |
118 | try {
119 | list = new ArrayList();
120 | JSONArray array = obj.getJSONArray("book");
121 | int length = array.length();
122 | for (int i = 0; i < length; i++) {
123 | JSONObject oj = array.getJSONObject(i);
124 |
125 | if (oj == null) {
126 | continue;
127 | }
128 |
129 | BookItem item = new BookItem();
130 | item.setLanguage(oj.optString("language"));
131 | item.setCountry(oj.optString("country"));
132 | item.setAuthor(oj.optString("author"));
133 | item.setTitle(oj.optString("title"));
134 | item.setDesc(oj.optString("desc"));
135 | item.setDefault(oj.optBoolean("default"));
136 | item.setUrl(oj.optString("url"));
137 | item.setImg(oj.optString("img"));
138 |
139 | list.add(item);
140 | }
141 | } catch (JSONException e) {
142 | e.printStackTrace();
143 | }
144 |
145 | return list;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/entity/Book.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books.entity;
2 |
3 | import android.text.TextUtils;
4 | import org.parceler.Parcel;
5 | import org.parceler.Transient;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Created by hui.yang on 2015/1/24.
11 | */
12 | @Parcel(Parcel.Serialization.METHOD)
13 | public class Book {
14 | private List list = null;
15 | private BookItem cacheBookItem = null;
16 | private String language = null;
17 |
18 | /**
19 | * get from cache
20 | *
21 | * @param language
22 | * @return
23 | */
24 | @Transient
25 | private BookItem getBookItemFromCache(String language){
26 | if (!TextUtils.isEmpty(this.language) && this.language.equalsIgnoreCase(language)){
27 | return cacheBookItem;
28 | }
29 | return null;
30 | }
31 |
32 | /**
33 | * set to cache
34 | *
35 | * @param item
36 | * @param language
37 | */
38 | @Transient
39 | private void setBookItemToCache(BookItem item,String language){
40 | this.language = language;
41 | this.cacheBookItem = item;
42 | }
43 |
44 |
45 | /**
46 | * whether the book is empty.
47 | *
48 | * @return
49 | */
50 | private boolean isEmpty(){
51 | if (list == null || list.isEmpty()){
52 | return true;
53 | }
54 |
55 | return false;
56 | }
57 |
58 | @Transient
59 | private BookItem getBookItem(String language){
60 | if (isEmpty()){
61 | return null;
62 | }
63 | BookItem bookItem = null;
64 | BookItem defaultBookItem = null;
65 |
66 | //get from cache
67 | BookItem cachebookItem = getBookItemFromCache(language);
68 | if (cachebookItem != null){
69 | bookItem = cachebookItem;
70 | return bookItem;
71 | }
72 |
73 | for (BookItem item: list){
74 | if (TextUtils.isEmpty(language)){
75 | if (item.isDefault()){
76 | bookItem = item;
77 | defaultBookItem = item;
78 | break;
79 | }
80 | }else{
81 | if (item.isDefault()){
82 | defaultBookItem = item;
83 | }
84 |
85 | if (language.equalsIgnoreCase(item.getLanguage())){
86 | bookItem = item;
87 | break;
88 | }
89 | }
90 | }
91 |
92 | if (bookItem == null && defaultBookItem != null){
93 | bookItem = defaultBookItem;
94 | }
95 |
96 |
97 | //set to cache
98 | if (bookItem != null && !TextUtils.isEmpty(language)){
99 | setBookItemToCache(bookItem,language);
100 | }
101 |
102 | return bookItem;
103 | }
104 |
105 | @Transient
106 | public String getLanguage(String language) {
107 | BookItem item = getBookItem(language);
108 | if (item != null){
109 | return item.getLanguage();
110 | }
111 |
112 | return null;
113 | }
114 |
115 | @Transient
116 | public String getCountry(String language) {
117 | BookItem item = getBookItem(language);
118 | if (item != null){
119 | return item.getCountry();
120 | }
121 |
122 | return null;
123 | }
124 |
125 | @Transient
126 | public String getAuthor(String language) {
127 | BookItem item = getBookItem(language);
128 | if (item != null){
129 | return item.getAuthor();
130 | }
131 |
132 | return null;
133 | }
134 |
135 | @Transient
136 | public String getTitle(String language) {
137 | BookItem item = getBookItem(language);
138 | if (item != null){
139 | return item.getTitle();
140 | }
141 |
142 | return null;
143 | }
144 |
145 | @Transient
146 | public String getDesc(String language) {
147 | BookItem item = getBookItem(language);
148 | if (item != null){
149 | return item.getDesc();
150 | }
151 |
152 | return null;
153 | }
154 |
155 | public boolean isDefault(String language) {
156 | BookItem item = getBookItem(language);
157 | if (item != null){
158 | return item.isDefault();
159 | }
160 |
161 | return false;
162 | }
163 |
164 | @Transient
165 | public String getUrl(String language) {
166 | BookItem item = getBookItem(language);
167 | if (item != null){
168 | return item.getUrl();
169 | }
170 |
171 | return null;
172 | }
173 |
174 | @Transient
175 | public String getImg(String language) {
176 | BookItem item = getBookItem(language);
177 | if (item != null){
178 | return item.getImg();
179 | }
180 |
181 | return null;
182 | }
183 |
184 | public List getList() {
185 | return list;
186 | }
187 |
188 | public void setList(List list) {
189 | this.list = list;
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/NavigationDrawerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books;
2 |
3 | import android.graphics.Color;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.MotionEvent;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.TextView;
10 | import com.github.snowdream.android.app.books.entity.Subject;
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * Created by poliveira on 24/10/2014.
16 | */
17 | public class NavigationDrawerAdapter extends RecyclerView.Adapter {
18 |
19 | private List mData;
20 | private NavigationDrawerCallbacks mNavigationDrawerCallbacks;
21 | private int mSelectedPosition;
22 | private int mTouchedPosition = -1;
23 |
24 | public NavigationDrawerAdapter(List data) {
25 | mData = data;
26 | }
27 |
28 | public NavigationDrawerCallbacks getNavigationDrawerCallbacks() {
29 | return mNavigationDrawerCallbacks;
30 | }
31 |
32 | public void setNavigationDrawerCallbacks(NavigationDrawerCallbacks navigationDrawerCallbacks) {
33 | mNavigationDrawerCallbacks = navigationDrawerCallbacks;
34 | }
35 |
36 | @Override
37 | public NavigationDrawerAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
38 | View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.drawer_row, viewGroup, false);
39 | return new ViewHolder(v);
40 | }
41 |
42 | @Override
43 | public void onBindViewHolder(NavigationDrawerAdapter.ViewHolder viewHolder, final int i) {
44 | Subject subject = mData.get(i).getSubject();
45 | viewHolder.textView.setText(subject.getName());
46 | viewHolder.textView.setCompoundDrawablesWithIntrinsicBounds(mData.get(i).getDrawable(), null, null, null);
47 |
48 | viewHolder.itemView.setOnTouchListener(new View.OnTouchListener() {
49 | @Override
50 | public boolean onTouch(View v, MotionEvent event) {
51 |
52 | switch (event.getAction()) {
53 | case MotionEvent.ACTION_DOWN:
54 | touchPosition(i);
55 | return false;
56 | case MotionEvent.ACTION_CANCEL:
57 | touchPosition(-1);
58 | return false;
59 | case MotionEvent.ACTION_MOVE:
60 | return false;
61 | case MotionEvent.ACTION_UP:
62 | touchPosition(-1);
63 | return false;
64 | }
65 | return true;
66 | }
67 | }
68 | );
69 | viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
70 | @Override
71 | public void onClick(View v) {
72 | if (mNavigationDrawerCallbacks != null)
73 | mNavigationDrawerCallbacks.onNavigationDrawerItemSelected(i);
74 | }
75 | }
76 | );
77 |
78 | //TODO: selected menu position, change layout accordingly
79 | if (mSelectedPosition == i || mTouchedPosition == i) {
80 | viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(R.color.selected_gray));
81 | } else {
82 | viewHolder.itemView.setBackgroundColor(Color.TRANSPARENT);
83 | }
84 | }
85 |
86 | private void touchPosition(int position) {
87 | int lastPosition = mTouchedPosition;
88 | mTouchedPosition = position;
89 | if (lastPosition >= 0)
90 | notifyItemChanged(lastPosition);
91 | if (position >= 0)
92 | notifyItemChanged(position);
93 | }
94 |
95 | public void selectPosition(int position) {
96 | int lastPosition = mSelectedPosition;
97 | mSelectedPosition = position;
98 | notifyItemChanged(lastPosition);
99 | notifyItemChanged(position);
100 | }
101 |
102 | @Override
103 | public int getItemCount() {
104 | return mData != null ? mData.size() : 0;
105 | }
106 |
107 | public static class ViewHolder extends RecyclerView.ViewHolder {
108 | public TextView textView;
109 |
110 | public ViewHolder(View itemView) {
111 | super(itemView);
112 | textView = (TextView) itemView.findViewById(R.id.item_name);
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/BookFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Snowdream Mobile
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.snowdream.android.app.books;
18 |
19 | import android.graphics.Bitmap;
20 | import android.os.Bundle;
21 | import android.support.v4.app.Fragment;
22 | import android.text.TextUtils;
23 | import android.view.KeyEvent;
24 | import android.view.LayoutInflater;
25 | import android.view.View;
26 | import android.view.ViewGroup;
27 | import android.webkit.*;
28 | import com.github.snowdream.android.util.Log;
29 | import com.google.android.gms.ads.AdRequest;
30 | import com.google.android.gms.ads.AdView;
31 |
32 | import java.util.Locale;
33 |
34 |
35 | public class BookFragment extends Fragment {
36 | private static final String TEST_DEVICE_ID = "INSERT_YOUR_TEST_DEVICE_ID_HERE";
37 | public static final String BOOK_URL_KEY = "BOOK_URL_KEY";
38 |
39 | private WebView webView = null;
40 |
41 | @Override
42 | public void onCreate(Bundle savedInstanceState) {
43 | super.onCreate(savedInstanceState);
44 | }
45 |
46 | @Override
47 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
48 | return inflater.inflate(R.layout.fragment_book, null);
49 | }
50 |
51 | @Override
52 | public void onViewCreated(View view, Bundle savedInstanceState) {
53 | super.onViewCreated(view, savedInstanceState);
54 | initUI(view);
55 | initData();
56 | }
57 |
58 | private void initUI(View rootview) {
59 | webView = (WebView) rootview.findViewById(R.id.webView);
60 | // progressbar = (SmoothProgressBar) rootview.findViewById(R.id.progressbar);
61 | WebSettings webSettings = webView.getSettings();
62 | webSettings.setJavaScriptEnabled(true);
63 | webSettings.setDomStorageEnabled(true);
64 | webSettings.setAllowFileAccess(true);
65 | webSettings.setSupportZoom(true);
66 | webSettings.setBuiltInZoomControls(true);
67 | webSettings.setUseWideViewPort(true);
68 | String appCachePath = getActivity().getApplicationContext().getCacheDir().getAbsolutePath();
69 | webSettings.setAppCachePath(appCachePath);
70 | webSettings.setAppCacheEnabled(true);
71 |
72 |
73 | webView.setWebViewClient(new WebViewClient() {
74 | @Override
75 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
76 | super.onPageStarted(view, url, favicon);
77 | // progressbar.setVisibility(View.VISIBLE);
78 | }
79 |
80 | @Override
81 | public void onPageFinished(WebView view, String url) {
82 | super.onPageFinished(view, url);
83 | // progressbar.setVisibility(View.INVISIBLE);
84 | }
85 |
86 | @Override
87 | public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
88 | super.onReceivedError(view, errorCode, description, failingUrl);
89 | // progressbar.setVisibility(View.INVISIBLE);
90 | }
91 | });
92 | webView.setWebChromeClient(new WebChromeClient() {
93 | @Override
94 | public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
95 | return super.onJsAlert(view, url, message, result);
96 | }
97 | });
98 |
99 |
100 |
101 | // The "loadAdOnCreate" and "testDevices" XML attributes no longer available.
102 | AdView adView = (AdView) rootview.findViewById(R.id.adView);
103 | AdRequest adRequest = new AdRequest.Builder()
104 | .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
105 | .addTestDevice(TEST_DEVICE_ID)
106 | .build();
107 | adView.loadAd(adRequest);
108 |
109 | getView().setFocusableInTouchMode(true);
110 | getView().setOnKeyListener( new View.OnKeyListener(){
111 | @Override
112 | public boolean onKey( View v, int keyCode, KeyEvent event ){
113 | if (webView.canGoBack() && keyCode == KeyEvent.KEYCODE_BACK) {
114 | webView.goBack();
115 |
116 | return true;
117 | }
118 | return false;
119 | }
120 | } );
121 | }
122 |
123 | private void initData() {
124 | Bundle bundle = getArguments();
125 | String book_url = bundle.getString(BOOK_URL_KEY);
126 |
127 | if (TextUtils.isEmpty(book_url)){
128 | Log.w("The Book Url is null or empty.");
129 | return;
130 | }
131 |
132 | webView.loadUrl(book_url);
133 | }
134 |
135 | @Override
136 | public void onDestroy() {
137 | webView.stopLoading();
138 | webView.destroy();
139 | super.onDestroy();
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/snowdream/android/app/books/NavigationDrawerFragment.java:
--------------------------------------------------------------------------------
1 | package com.github.snowdream.android.app.books;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 | import android.content.res.Configuration;
7 | import android.os.Bundle;
8 | import android.support.annotation.Nullable;
9 | import android.support.v4.app.Fragment;
10 | import android.support.v4.widget.DrawerLayout;
11 | import android.support.v7.app.ActionBarDrawerToggle;
12 | import android.support.v7.widget.LinearLayoutManager;
13 | import android.support.v7.widget.RecyclerView;
14 | import android.support.v7.widget.Toolbar;
15 | import android.view.LayoutInflater;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 |
19 | import java.util.List;
20 |
21 | /**
22 | * Created by poliveira on 24/10/2014.
23 | */
24 | public class NavigationDrawerFragment extends Fragment implements NavigationDrawerCallbacks {
25 | private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
26 | private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
27 | private static final String PREFERENCES_FILE = "my_app_settings"; //TODO: change this to your file
28 | public static final String KEY_NAVIGATION_ITEM = "key_navigation_item";
29 |
30 | private NavigationDrawerCallbacks mCallbacks;
31 | private RecyclerView mDrawerList;
32 | private View mFragmentContainerView;
33 | private DrawerLayout mDrawerLayout;
34 | private ActionBarDrawerToggle mActionBarDrawerToggle;
35 | private boolean mUserLearnedDrawer;
36 | private boolean mFromSavedInstanceState;
37 | private int mCurrentSelectedPosition;
38 | private List items = null;
39 |
40 |
41 | @Nullable
42 | @Override
43 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
44 | View view = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
45 | mDrawerList = (RecyclerView) view.findViewById(R.id.drawerList);
46 | LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
47 | layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
48 | mDrawerList.setLayoutManager(layoutManager);
49 | mDrawerList.setHasFixedSize(true);
50 |
51 | return view;
52 | }
53 |
54 | @Override
55 | public void onCreate(Bundle savedInstanceState) {
56 | super.onCreate(savedInstanceState);
57 | mUserLearnedDrawer = Boolean.valueOf(readSharedSetting(getActivity(), PREF_USER_LEARNED_DRAWER, "false"));
58 | if (savedInstanceState != null) {
59 | mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
60 | mFromSavedInstanceState = true;
61 | }
62 | }
63 |
64 | @Override
65 | public void onAttach(Activity activity) {
66 | super.onAttach(activity);
67 | try {
68 | mCallbacks = (NavigationDrawerCallbacks) activity;
69 | } catch (ClassCastException e) {
70 | throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
71 | }
72 | }
73 |
74 | public ActionBarDrawerToggle getActionBarDrawerToggle() {
75 | return mActionBarDrawerToggle;
76 | }
77 |
78 | public void setActionBarDrawerToggle(ActionBarDrawerToggle actionBarDrawerToggle) {
79 | mActionBarDrawerToggle = actionBarDrawerToggle;
80 | }
81 |
82 | public void setMenu(List list){
83 | items = list;
84 | }
85 |
86 | public void refresh(){
87 | final List navigationItems = getMenu();
88 | NavigationDrawerAdapter adapter = new NavigationDrawerAdapter(navigationItems);
89 | adapter.setNavigationDrawerCallbacks(this);
90 | mDrawerList.setAdapter(adapter);
91 | selectItem(mCurrentSelectedPosition);
92 | }
93 |
94 | public void setup(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
95 | mFragmentContainerView = getActivity().findViewById(fragmentId);
96 | mDrawerLayout = drawerLayout;
97 | mDrawerLayout.setStatusBarBackgroundColor(
98 | getResources().getColor(R.color.myPrimaryDarkColor));
99 |
100 | mActionBarDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
101 | @Override
102 | public void onDrawerClosed(View drawerView) {
103 | super.onDrawerClosed(drawerView);
104 | if (!isAdded()) return;
105 | getActivity().supportInvalidateOptionsMenu();
106 | }
107 |
108 | @Override
109 | public void onDrawerOpened(View drawerView) {
110 | super.onDrawerOpened(drawerView);
111 | if (!isAdded()) return;
112 | if (!mUserLearnedDrawer) {
113 | mUserLearnedDrawer = true;
114 | saveSharedSetting(getActivity(), PREF_USER_LEARNED_DRAWER, "true");
115 | }
116 |
117 | getActivity().supportInvalidateOptionsMenu();
118 | }
119 | };
120 |
121 | if (!mUserLearnedDrawer && !mFromSavedInstanceState)
122 | mDrawerLayout.openDrawer(mFragmentContainerView);
123 |
124 | mDrawerLayout.post(new Runnable() {
125 | @Override
126 | public void run() {
127 | mActionBarDrawerToggle.syncState();
128 | }
129 | });
130 |
131 | mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
132 | }
133 |
134 | public void openDrawer() {
135 | mDrawerLayout.openDrawer(mFragmentContainerView);
136 | }
137 |
138 | public void closeDrawer() {
139 | mDrawerLayout.closeDrawer(mFragmentContainerView);
140 | }
141 |
142 | @Override
143 | public void onDetach() {
144 | super.onDetach();
145 | mCallbacks = null;
146 | }
147 |
148 | public List getMenu() {
149 | return items;
150 | }
151 |
152 | void selectItem(int position) {
153 | mCurrentSelectedPosition = position;
154 | if (mDrawerLayout != null) {
155 | mDrawerLayout.closeDrawer(mFragmentContainerView);
156 | }
157 | if (mCallbacks != null) {
158 | mCallbacks.onNavigationDrawerItemSelected(position);
159 | }
160 | ((NavigationDrawerAdapter) mDrawerList.getAdapter()).selectPosition(position);
161 | }
162 |
163 | public boolean isDrawerOpen() {
164 | return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
165 | }
166 |
167 | @Override
168 | public void onConfigurationChanged(Configuration newConfig) {
169 | super.onConfigurationChanged(newConfig);
170 | mActionBarDrawerToggle.onConfigurationChanged(newConfig);
171 | }
172 |
173 | @Override
174 | public void onSaveInstanceState(Bundle outState) {
175 | super.onSaveInstanceState(outState);
176 | outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
177 | }
178 |
179 | @Override
180 | public void onNavigationDrawerItemSelected(int position) {
181 | selectItem(position);
182 | }
183 |
184 | public DrawerLayout getDrawerLayout() {
185 | return mDrawerLayout;
186 | }
187 |
188 | public void setDrawerLayout(DrawerLayout drawerLayout) {
189 | mDrawerLayout = drawerLayout;
190 | }
191 |
192 | public static void saveSharedSetting(Context ctx, String settingName, String settingValue) {
193 | SharedPreferences sharedPref = ctx.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
194 | SharedPreferences.Editor editor = sharedPref.edit();
195 | editor.putString(settingName, settingValue);
196 | editor.apply();
197 | }
198 |
199 | public static String readSharedSetting(Context ctx, String settingName, String defaultValue) {
200 | SharedPreferences sharedPref = ctx.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
201 | return sharedPref.getString(settingName, defaultValue);
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction, and
10 | distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright
13 | owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all other entities
16 | that control, are controlled by, or are under common control with that entity.
17 | For the purposes of this definition, "control" means (i) the power, direct or
18 | indirect, to cause the direction or management of such entity, whether by
19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20 | outstanding shares, or (iii) beneficial ownership of such entity.
21 |
22 | "You" (or "Your") shall mean an individual or Legal Entity exercising
23 | permissions granted by this License.
24 |
25 | "Source" form shall mean the preferred form for making modifications, including
26 | but not limited to software source code, documentation source, and configuration
27 | files.
28 |
29 | "Object" form shall mean any form resulting from mechanical transformation or
30 | translation of a Source form, including but not limited to compiled object code,
31 | generated documentation, and conversions to other media types.
32 |
33 | "Work" shall mean the work of authorship, whether in Source or Object form, made
34 | available under the License, as indicated by a copyright notice that is included
35 | in or attached to the work (an example is provided in the Appendix below).
36 |
37 | "Derivative Works" shall mean any work, whether in Source or Object form, that
38 | is based on (or derived from) the Work and for which the editorial revisions,
39 | annotations, elaborations, or other modifications represent, as a whole, an
40 | original work of authorship. For the purposes of this License, Derivative Works
41 | shall not include works that remain separable from, or merely link (or bind by
42 | name) to the interfaces of, the Work and Derivative Works thereof.
43 |
44 | "Contribution" shall mean any work of authorship, including the original version
45 | of the Work and any modifications or additions to that Work or Derivative Works
46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work
47 | by the copyright owner or by an individual or Legal Entity authorized to submit
48 | on behalf of the copyright owner. For the purposes of this definition,
49 | "submitted" means any form of electronic, verbal, or written communication sent
50 | to the Licensor or its representatives, including but not limited to
51 | communication on electronic mailing lists, source code control systems, and
52 | issue tracking systems that are managed by, or on behalf of, the Licensor for
53 | the purpose of discussing and improving the Work, but excluding communication
54 | that is conspicuously marked or otherwise designated in writing by the copyright
55 | owner as "Not a Contribution."
56 |
57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58 | of whom a Contribution has been received by Licensor and subsequently
59 | incorporated within the Work.
60 |
61 | 2. Grant of Copyright License.
62 |
63 | Subject to the terms and conditions of this License, each Contributor hereby
64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65 | irrevocable copyright license to reproduce, prepare Derivative Works of,
66 | publicly display, publicly perform, sublicense, and distribute the Work and such
67 | Derivative Works in Source or Object form.
68 |
69 | 3. Grant of Patent License.
70 |
71 | Subject to the terms and conditions of this License, each Contributor hereby
72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73 | irrevocable (except as stated in this section) patent license to make, have
74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75 | such license applies only to those patent claims licensable by such Contributor
76 | that are necessarily infringed by their Contribution(s) alone or by combination
77 | of their Contribution(s) with the Work to which such Contribution(s) was
78 | submitted. If You institute patent litigation against any entity (including a
79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80 | Contribution incorporated within the Work constitutes direct or contributory
81 | patent infringement, then any patent licenses granted to You under this License
82 | for that Work shall terminate as of the date such litigation is filed.
83 |
84 | 4. Redistribution.
85 |
86 | You may reproduce and distribute copies of the Work or Derivative Works thereof
87 | in any medium, with or without modifications, and in Source or Object form,
88 | provided that You meet the following conditions:
89 |
90 | You must give any other recipients of the Work or Derivative Works a copy of
91 | this License; and
92 | You must cause any modified files to carry prominent notices stating that You
93 | changed the files; and
94 | You must retain, in the Source form of any Derivative Works that You distribute,
95 | all copyright, patent, trademark, and attribution notices from the Source form
96 | of the Work, excluding those notices that do not pertain to any part of the
97 | Derivative Works; and
98 | If the Work includes a "NOTICE" text file as part of its distribution, then any
99 | Derivative Works that You distribute must include a readable copy of the
100 | attribution notices contained within such NOTICE file, excluding those notices
101 | that do not pertain to any part of the Derivative Works, in at least one of the
102 | following places: within a NOTICE text file distributed as part of the
103 | Derivative Works; within the Source form or documentation, if provided along
104 | with the Derivative Works; or, within a display generated by the Derivative
105 | Works, if and wherever such third-party notices normally appear. The contents of
106 | the NOTICE file are for informational purposes only and do not modify the
107 | License. You may add Your own attribution notices within Derivative Works that
108 | You distribute, alongside or as an addendum to the NOTICE text from the Work,
109 | provided that such additional attribution notices cannot be construed as
110 | modifying the License.
111 | You may add Your own copyright statement to Your modifications and may provide
112 | additional or different license terms and conditions for use, reproduction, or
113 | distribution of Your modifications, or for any such Derivative Works as a whole,
114 | provided Your use, reproduction, and distribution of the Work otherwise complies
115 | with the conditions stated in this License.
116 |
117 | 5. Submission of Contributions.
118 |
119 | Unless You explicitly state otherwise, any Contribution intentionally submitted
120 | for inclusion in the Work by You to the Licensor shall be under the terms and
121 | conditions of this License, without any additional terms or conditions.
122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of
123 | any separate license agreement you may have executed with Licensor regarding
124 | such Contributions.
125 |
126 | 6. Trademarks.
127 |
128 | This License does not grant permission to use the trade names, trademarks,
129 | service marks, or product names of the Licensor, except as required for
130 | reasonable and customary use in describing the origin of the Work and
131 | reproducing the content of the NOTICE file.
132 |
133 | 7. Disclaimer of Warranty.
134 |
135 | Unless required by applicable law or agreed to in writing, Licensor provides the
136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138 | including, without limitation, any warranties or conditions of TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140 | solely responsible for determining the appropriateness of using or
141 | redistributing the Work and assume any risks associated with Your exercise of
142 | permissions under this License.
143 |
144 | 8. Limitation of Liability.
145 |
146 | In no event and under no legal theory, whether in tort (including negligence),
147 | contract, or otherwise, unless required by applicable law (such as deliberate
148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be
149 | liable to You for damages, including any direct, indirect, special, incidental,
150 | or consequential damages of any character arising as a result of this License or
151 | out of the use or inability to use the Work (including but not limited to
152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153 | any and all other commercial damages or losses), even if such Contributor has
154 | been advised of the possibility of such damages.
155 |
156 | 9. Accepting Warranty or Additional Liability.
157 |
158 | While redistributing the Work or Derivative Works thereof, You may choose to
159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160 | other liability obligations and/or rights consistent with this License. However,
161 | in accepting such obligations, You may act only on Your own behalf and on Your
162 | sole responsibility, not on behalf of any other Contributor, and only if You
163 | agree to indemnify, defend, and hold each Contributor harmless for any liability
164 | incurred by, or claims asserted against, such Contributor by reason of your
165 | accepting any such warranty or additional liability.
166 |
167 | END OF TERMS AND CONDITIONS
168 |
169 | APPENDIX: How to apply the Apache License to your work
170 |
171 | To apply the Apache License to your work, attach the following boilerplate
172 | notice, with the fields enclosed by brackets "[]" replaced with your own
173 | identifying information. (Don't include the brackets!) The text should be
174 | enclosed in the appropriate comment syntax for the file format. We also
175 | recommend that a file or class name and description of purpose be included on
176 | the same "printed page" as the copyright notice for easier identification within
177 | third-party archives.
178 |
179 | Copyright [yyyy] [name of copyright owner]
180 |
181 | Licensed under the Apache License, Version 2.0 (the "License");
182 | you may not use this file except in compliance with the License.
183 | You may obtain a copy of the License at
184 |
185 | http://www.apache.org/licenses/LICENSE-2.0
186 |
187 | Unless required by applicable law or agreed to in writing, software
188 | distributed under the License is distributed on an "AS IS" BASIS,
189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190 | See the License for the specific language governing permissions and
191 | limitations under the License.
192 |
--------------------------------------------------------------------------------
/docs/test/recomend.json:
--------------------------------------------------------------------------------
1 | {
2 | "books": [
3 | {
4 | "book": [
5 | {
6 | "language": "zh",
7 | "country": "CN",
8 | "author": "梁杰",
9 | "title": "The Swift Programming Language 中文版",
10 | "desc": "The Swift Programming Language 中文版",
11 | "default": true,
12 | "url": "http://numbbbbb.gitbooks.io/-the-swift-programming-language-/content/",
13 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/numbbbbb/-the-swift-programming-language-.jpg?build=1422352186169&v=6.3.4"
14 | },
15 | {
16 | "language": "zh",
17 | "country": "TW",
18 | "author": "Tommy Lin",
19 | "title": "The Swift Programming Language 正體中文版",
20 | "desc": "正體中文版蘋果 Swift 官方教學《The Swift Programming Language》",
21 | "default": false,
22 | "url": "https://www.gitbook.com/read/book/tommy60703/swift-language-traditional-chinese",
23 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/tommy60703/swift-language-traditional-chinese.jpg?build=1416974934692&v=6.3.4"
24 | }
25 | ]
26 | },
27 | {
28 | "book": [
29 | {
30 | "language": "en",
31 | "country": "US",
32 | "author": "plt",
33 | "title": "Seafile Server Manual",
34 | "desc": "Manual of Seafile Server",
35 | "default": true,
36 | "url": "http://manual.seafile.com/",
37 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/freeplant/seafile-server-manual.jpg?build=1421919619980&v=6.3.4"
38 | },
39 | {
40 | "language": "zh",
41 | "country": "CN",
42 | "author": "plt",
43 | "title": "Seafile服务器手册中文版",
44 | "desc": "Seafile 是一个开源的文件云存储平台。它提供更丰富的文件同步和管理功能,以及更好的数据隐私保护和群组协作功能。",
45 | "default": false,
46 | "url": "http://manual-cn.seafile.com/",
47 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/freeplant/seafile-server-manual.jpg?build=1421919619980&v=6.3.4"
48 | }
49 | ]
50 | },
51 | {
52 | "book": [
53 | {
54 | "language": "en",
55 | "country": "US",
56 | "author": "Jeremy Saenz",
57 | "title": "Building Web Apps with Go",
58 | "desc": "Learn how to build and deploy web applications with Go.",
59 | "default": true,
60 | "url": "http://codegangsta.gitbooks.io/building-web-apps-with-go/content/",
61 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/codegangsta/building-web-apps-with-go.jpg?build=1417051877195&v=6.3.4"
62 | }
63 | ]
64 | },
65 | {
66 | "book": [
67 | {
68 | "language": "zh",
69 | "country": "CN",
70 | "author": "yeasy",
71 | "title": "Docker —— 从入门到实践",
72 | "desc": "本书既适用于具备基础 Linux 知识的 Docker 初学者,也可供希望理解原理和实现的高级用户参考。同时,书中给出的实践案例,可供在进行实际部署时借鉴。",
73 | "default": true,
74 | "url": "http://yeasy.gitbooks.io/docker_practice/content/",
75 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/yeasy/docker_practice.jpg?build=1421893844822&v=6.3.4"
76 | },
77 | {
78 | "language": "zh",
79 | "country": "TW",
80 | "author": "philipzheng",
81 | "title": "《Docker —— 從入門到實踐》正體中文版",
82 | "desc": "出處:Docker —— 从入门到实践 ",
83 | "default": false,
84 | "url": "https://www.gitbook.com/read/book/philipzheng/docker_practice",
85 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/philipzheng/docker_practice.jpg?build=1418779400405&v=6.3.4"
86 | }
87 | ]
88 | },
89 | {
90 | "book": [
91 | {
92 | "language": "en",
93 | "country": "US",
94 | "author": "Frank Denis",
95 | "title": "libsodium",
96 | "desc": "A high-security, cross-platform, easy-to-use crypto library.",
97 | "default": true,
98 | "url": "http://doc.libsodium.org/",
99 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/jedisct1/libsodium.jpg?build=1421921622089&v=6.3.4"
100 | }
101 | ]
102 | },
103 | {
104 | "book": [
105 | {
106 | "language": "en",
107 | "country": "US",
108 | "author": "DjangoGirls , Ola Sitarska , Ola Sendecka and Baptiste Mispelon",
109 | "title": "Django Girls Tutorial",
110 | "desc": "This book is a Django tutorial created for DjangoGirls event.",
111 | "default": true,
112 | "url": "https://www.gitbook.com/read/book/djangogirls/djangogirls-tutorial",
113 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/djangogirls/djangogirls-tutorial.jpg?build=1420795447441&v=6.3.4"
114 | }
115 | ]
116 | },
117 | {
118 | "book": [
119 | {
120 | "language": "jp",
121 | "country": "JP",
122 | "author": "tarukosu",
123 | "title": "現役東大院生が教える高校数学の考え方",
124 | "desc": "This book is a Django tutorial created for DjangoGirls event.",
125 | "default": true,
126 | "url": "https://www.gitbook.com/read/book/tarukosu/mathbook",
127 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/tarukosu/mathbook.jpg?build=1414796385436&v=6.3.4"
128 | }
129 | ]
130 | },
131 | {
132 | "book": [
133 | {
134 | "language": "zh",
135 | "country": "TW",
136 | "author": "wcc723",
137 | "title": "Google Material Design 正體中文版",
138 | "desc": "Google Material Design 正體中文版",
139 | "default": true,
140 | "url": "http://wcc723.gitbooks.io/google_design_translate/content/",
141 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/wcc723/google_design_translate.jpg?build=1420620075081&v=6.3.4"
142 | }
143 | ]
144 | },
145 | {
146 | "book": [
147 | {
148 | "language": "zh",
149 | "country": "CN",
150 | "author": "Donald Tu",
151 | "title": "OpenWrt智能、自动、透明翻墙路由器教程",
152 | "desc": "手把手教你路由器刷OpenWrt固件,自动穿越万里长城",
153 | "default": true,
154 | "url": "https://www.gitbook.com/read/book/softwaredownload/openwrt-fanqiang",
155 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/softwaredownload/openwrt-fanqiang.jpg?build=1417048955696&v=6.3.4"
156 | }
157 | ]
158 | },
159 | {
160 | "book": [
161 | {
162 | "language": "en",
163 | "country": "US",
164 | "author": "Samy Pessé",
165 | "title": "How to make an Operating System",
166 | "desc": "Online book about how to write a computer operating system in C/C++ from scratch.",
167 | "default": true,
168 | "url": "http://samypesse.gitbooks.io/how-to-create-an-operating-system/content/",
169 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/samypesse/how-to-create-an-operating-system.jpg?build=1418850966857&v=6.3.4"
170 | }
171 | ]
172 | },
173 | {
174 | "book": [
175 | {
176 | "language": "zh",
177 | "country": "TW",
178 | "author": "雨蒼 and 洪偉",
179 | "title": "讓你真的讀懂草案的「自經區爭議書」",
180 | "desc": "全法條摘要、各章節要點整理、十四個經典爭議,讓你一手掌握自經區當前爭論所在!",
181 | "default": true,
182 | "url": "https://www.gitbook.com/read/book/billy3321/taiwanfepzs",
183 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/billy3321/taiwanfepzs.jpg?build=1416957340837&v=6.3.4"
184 | }
185 | ]
186 | },
187 | {
188 | "book": [
189 | {
190 | "language": "en",
191 | "country": "US",
192 | "author": "Mohammad Hossein Mojtahedi",
193 | "title": "Swift Cheat Sheet",
194 | "desc": "A short guide to using Apple's new programming language, Swift.",
195 | "default": true,
196 | "url": "https://www.gitbook.com/read/book/mhm5000/swift-cheat-sheet",
197 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/mhm5000/swift-cheat-sheet.jpg?build=1416966376809&v=6.3.4"
198 | }
199 | ]
200 | },
201 | {
202 | "book": [
203 | {
204 | "language": "en",
205 | "country": "US",
206 | "author": "GitBook",
207 | "title": "Learn Javascript",
208 | "desc": "This book will teach you the basics of programming and Javascript. ",
209 | "default": true,
210 | "url": "http://gitbookio.gitbooks.io/javascript/",
211 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/gitbookio/javascript.jpg?build=1418385941206&v=6.3.4"
212 | }
213 | ]
214 | },
215 | {
216 | "book": [
217 | {
218 | "language": "en",
219 | "country": "US",
220 | "author": "GitBook",
221 | "title": "GitBook Documentation",
222 | "desc": "This book contains the entire documentation for GitBook (platform and toolchain).",
223 | "default": true,
224 | "url": "http://help.gitbook.io/",
225 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/gitbookio/documentation.jpg?build=1420932119816&v=6.3.4"
226 | }
227 | ]
228 | },
229 | {
230 | "book": [
231 | {
232 | "language": "en",
233 | "country": "US",
234 | "author": "GitBook",
235 | "title": "Pro Git",
236 | "desc": "A GitBook version of the famous Pro Git book written by Scott Chacon.",
237 | "default": true,
238 | "url": "https://www.gitbook.com/read/book/gitbookio/progit",
239 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/gitbookio/progit.jpg?build=1414793393766&v=6.3.4"
240 | }
241 | ]
242 | },
243 | {
244 | "book": [
245 | {
246 | "language": "en",
247 | "country": "US",
248 | "author": "GitBook",
249 | "title": "Learn Markdown",
250 | "desc": "Learn how to write great documents using Markdown.",
251 | "default": true,
252 | "url": "https://www.gitbook.com/read/book/gitbookio/markdown",
253 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/gitbookio/markdown.jpg?build=1414791083337&v=6.3.4"
254 | }
255 | ]
256 | },
257 | {
258 | "book": [
259 | {
260 | "language": "zh",
261 | "country": "CN",
262 | "author": "Fu Kailong",
263 | "title": "ElasticSearch 权威指南",
264 | "desc": "ElasticSearch 权威指南",
265 | "default": true,
266 | "url": "https://www.gitbook.com/read/book/fuxiaopang/learnelasticsearch",
267 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/fuxiaopang/learnelasticsearch.jpg?build=1414839122394&v=6.3.4"
268 | }
269 | ]
270 | },
271 | {
272 | "book": [
273 | {
274 | "language": "en",
275 | "country": "US",
276 | "author": "snipe",
277 | "title": "Snipe-IT Installation Guide & User's Manual",
278 | "desc": "Snipe-IT Installation Guide & User's Manual",
279 | "default": true,
280 | "url": "http://snipe.gitbooks.io/snipe-it-manual/",
281 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/snipe/snipe-it-manual.jpg?build=1417053830514&v=6.3.4"
282 | }
283 | ]
284 | },
285 | {
286 | "book": [
287 | {
288 | "language": "en",
289 | "country": "US",
290 | "author": "snipe",
291 | "title": "Famous Mobile Apps",
292 | "desc": "From the creator of Wehicle and Hackathon.io",
293 | "default": true,
294 | "url": "http://book.famousmobileapps.com/",
295 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/nicholasareed/playbook-to-build-apps-with-phonegap-famous.jpg?build=1421713445984&v=6.3.4"
296 | }
297 | ]
298 | },
299 | {
300 | "book": [
301 | {
302 | "language": "zh",
303 | "country": "CN",
304 | "author": "tobe",
305 | "title": "理解Linux进程",
306 | "desc": "理解Linux进程",
307 | "default": true,
308 | "url": "http://www.linuxprocess.com/",
309 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/tobegit3hub1/understanding-linux-processes.jpg?build=1422417487455&v=6.3.4"
310 | }
311 | ]
312 | },
313 | {
314 | "book": [
315 | {
316 | "language": "en",
317 | "country": "US",
318 | "author": "databricks",
319 | "title": "Databricks Spark Reference Applications",
320 | "desc": "Reference Applications demonstrating Apache Spark - brought to you by Databricks.",
321 | "default": true,
322 | "url": "http://databricks.gitbooks.io/databricks-spark-reference-applications/content/",
323 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/databricks/databricks-spark-reference-applications.jpg?build=1417048541908&v=6.3.4"
324 | }
325 | ]
326 | },
327 | {
328 | "book": [
329 | {
330 | "language": "zh",
331 | "country": "TW",
332 | "author": "rocodev , xdite and WayneChu",
333 | "title": "Rails 102",
334 | "desc": "Rails 102",
335 | "default": true,
336 | "url": "http://rocodev.gitbooks.io/rails-102/content/",
337 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/rocodev/rails-102.jpg?build=1416972033497&v=6.3.4"
338 | }
339 | ]
340 | },
341 | {
342 | "book": [
343 | {
344 | "language": "en",
345 | "country": "US",
346 | "author": "Samy Pessé",
347 | "title": "Marc Andreessen Tweetstorms",
348 | "desc": "Collection of essays from Marc Andreessen (entrepreneur, investor, and software engineer) published on Twitter.",
349 | "default": true,
350 | "url": "http://samypesse.gitbooks.io/pmarca-notes/",
351 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/samypesse/pmarca-notes.jpg?build=1414805919248&v=6.3.4"
352 | }
353 | ]
354 | },
355 | {
356 | "book": [
357 | {
358 | "language": "en",
359 | "country": "US",
360 | "author": "97 Things Every X Should Know",
361 | "title": "97 Things Every Programmer Should Know",
362 | "desc": "Pearls of wisdom for programmers collected from leading practitioners.",
363 | "default": true,
364 | "url": "https://www.gitbook.com/read/book/97-things-every-x-should-know/97-things-every-programmer-should-know",
365 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/97-things-every-x-should-know/97-things-every-programmer-should-know.jpg?build=1422649438761&v=6.3.4"
366 | }
367 | ]
368 | },
369 | {
370 | "book": [
371 | {
372 | "language": "en",
373 | "country": "US",
374 | "author": "MakerSquare",
375 | "title": "Applying to MakerSquare",
376 | "desc": "Learn the basics of Ruby while applying to MakerSquare, a programming school in San Francisco, CA & Austin, TX.",
377 | "default": true,
378 | "url": "https://www.gitbook.com/read/book/makersquare/preparing-for-makersquare",
379 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/makersquare/preparing-for-makersquare.jpg?build=1418071121677&v=6.3.4"
380 | }
381 | ]
382 | },
383 | {
384 | "book": [
385 | {
386 | "language": "en",
387 | "country": "US",
388 | "author": "Tom J Nowell",
389 | "title": "WordPress The Right Way",
390 | "desc": "WIP Book",
391 | "default": true,
392 | "url": "https://www.gitbook.com/read/book/tarendai/wordpress-the-right-way",
393 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/tarendai/wordpress-the-right-way.jpg?build=1421420739802&v=6.3.4"
394 | }
395 | ]
396 | },
397 | {
398 | "book": [
399 | {
400 | "language": "en",
401 | "country": "US",
402 | "author": "snowdream",
403 | "title": "github-cheat-sheet",
404 | "desc": "A collection of cool hidden and not so hidden features of Git and GitHub. ",
405 | "default": true,
406 | "url": "http://snowdream86.gitbooks.io/github-cheat-sheet/content/",
407 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/snowdream86/github-cheat-sheet.jpg?build=1416974605786&v=6.3.4"
408 | }
409 | ]
410 | },
411 | {
412 | "book": [
413 | {
414 | "language": "zh",
415 | "country": "CN",
416 | "author": "lv",
417 | "title": "Git-Tutorial",
418 | "desc": "A Git Tutorial By liaoxuefeng ",
419 | "default": true,
420 | "url": "http://lvwzhen.gitbooks.io/git-tutorial/content/",
421 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/lvwzhen/git-tutorial.jpg?build=1416965152102&v=6.3.4"
422 | }
423 | ]
424 | },
425 | {
426 | "book": [
427 | {
428 | "language": "en",
429 | "country": "US",
430 | "author": "Dale Sande",
431 | "title": "Git for Everyone",
432 | "desc": "he Git Workshop Guide ",
433 | "default": true,
434 | "url": "https://www.gitbook.com/read/book/anotheruiguy/gitforeveryone",
435 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/anotheruiguy/gitforeveryone.jpg?build=1414787507253&v=6.3.4"
436 | }
437 | ]
438 | },
439 | {
440 | "book": [
441 | {
442 | "language": "zh",
443 | "country": "CN",
444 | "author": "饶琛琳",
445 | "title": "Kibana 中文指南",
446 | "desc": "翻译官网指南 kibana 部分,并补充了自己的 panels 说明,代码解析等",
447 | "default": true,
448 | "url": "https://www.gitbook.com/read/book/chenryn/kibana-guide-cn",
449 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/chenryn/kibana-guide-cn.jpg?build=1422346273259&v=6.3.4"
450 | }
451 | ]
452 | },
453 | {
454 | "book": [
455 | {
456 | "language": "en",
457 | "country": "US",
458 | "author": "maxolson",
459 | "title": "Blue Chip Stamps",
460 | "desc": "The annual letters for Blue Chip Stamps from 1978 to 1982, written by Charlie Munger.",
461 | "default": true,
462 | "url": "https://www.gitbook.com/read/book/maxolson/blue-chip-stamps",
463 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/maxolson/blue-chip-stamps.jpg?build=1417287295299&v=6.3.4"
464 | }
465 | ]
466 | },
467 | {
468 | "book": [
469 | {
470 | "language": "en",
471 | "country": "US",
472 | "author": "h2o",
473 | "title": "H2O World Training",
474 | "desc": "Full day of immersive training with H2O.",
475 | "default": true,
476 | "url": "https://www.gitbook.com/read/book/h2o/h2o-training-day",
477 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/h2o/h2o-training-day.jpg?build=1421967851702&v=6.3.4"
478 | }
479 | ]
480 | },
481 | {
482 | "book": [
483 | {
484 | "language": "zh",
485 | "country": "CN",
486 | "author": "Zach",
487 | "title": "AngularJS学习笔记",
488 | "desc": "AngularJS学习笔记",
489 | "default": true,
490 | "url": "https://www.gitbook.com/read/book/checkcheckzz/angularjs-learning-notes",
491 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/checkcheckzz/angularjs-learning-notes.jpg?build=1418901431589&v=6.3.4"
492 | }
493 | ]
494 | },
495 | {
496 | "book": [
497 | {
498 | "language": "zh",
499 | "country": "CN",
500 | "author": "Zach",
501 | "title": "Appium 中文教程",
502 | "desc": "Appium 中文教程",
503 | "default": true,
504 | "url": "https://www.gitbook.com/read/book/lihuazhang/appium-chinese-tutorial",
505 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/lihuazhang/appium-chinese-tutorial.jpg?build=1414796810918&v=6.3.4"
506 | }
507 | ]
508 | },
509 | {
510 | "book": [
511 | {
512 | "language": "zh",
513 | "country": "TW",
514 | "author": "Fu Kailong",
515 | "title": "勞權律師蔡瑞麟【2014台北市勞動局長參選】政見簡述",
516 | "desc": "勞權律師蔡瑞麟【2014台北市勞動局長參選】政見簡述",
517 | "default": true,
518 | "url": "https://www.gitbook.com/read/book/arny/arnypolicy2014",
519 | "img": "https://sm3lir.cloudimage.io/s/width/210/https://www.gitbook.com/cover/book/arny/arnypolicy2014.jpg?build=1418319355584&v=6.3.4"
520 | }
521 | ]
522 | }
523 | ]
524 | }
--------------------------------------------------------------------------------