Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Szaki
xkcd-browser
Commits
1c6f2322
Unverified
Commit
1c6f2322
authored
Apr 17, 2018
by
Tamás Szabó
Committed by
GitHub
Apr 17, 2018
Browse files
Merge pull request #9 from szakitom/development
labor5
parents
314db438
445eb50e
Changes
27
Hide whitespace changes
Inline
Side-by-side
.idea/caches/build_file_checksums.ser
View file @
1c6f2322
No preview for this file type
.idea/misc.xml
View file @
1c6f2322
...
...
@@ -24,7 +24,7 @@
</value>
</option>
</component>
<component
name=
"ProjectRootManager"
version=
"2"
languageLevel=
"JDK_1_
7
"
project-jdk-name=
"1.8"
project-jdk-type=
"JavaSDK"
>
<component
name=
"ProjectRootManager"
version=
"2"
languageLevel=
"JDK_1_
8
"
project-jdk-name=
"1.8"
project-jdk-type=
"JavaSDK"
>
<output
url=
"file://$PROJECT_DIR$/build/classes"
/>
</component>
<component
name=
"ProjectType"
>
...
...
app/build.gradle
View file @
1c6f2322
...
...
@@ -26,6 +26,31 @@ android {
}
}
packagingOptions
{
exclude
'META-INF/DEPENDENCIES'
exclude
'META-INF/LICENSE'
exclude
'META-INF/LICENSE.txt'
exclude
'META-INF/license.txt'
exclude
'META-INF/NOTICE'
exclude
'META-INF/NOTICE.txt'
exclude
'META-INF/notice.txt'
exclude
'META-INF/ASL2.0'
}
lintOptions
{
abortOnError
false
}
}
ext
{
okhttp_version
=
"3.0.1"
oltu_version
=
"1.0.0"
retrofit_version
=
"2.0.0-beta3"
gson_version
=
"2.4"
swagger_annotations_version
=
"1.5.0"
junit_version
=
"4.12"
}
dependencies
{
...
...
@@ -45,5 +70,17 @@ dependencies {
annotationProcessor
'com.google.dagger:dagger-android-processor:2.11'
implementation
'com.google.dagger:dagger-android:2.11'
compileOnly
'javax.annotation:jsr250-api:1.0'
// RetroFit
implementation
"com.squareup.okhttp3:okhttp:$okhttp_version"
implementation
"com.squareup.retrofit2:retrofit:$retrofit_version"
implementation
"com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation
"com.google.code.gson:gson:$gson_version"
implementation
"io.swagger:swagger-annotations:$swagger_annotations_version"
implementation
"org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"
// Room
implementation
'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor
'android.arch.persistence.room:compiler:1.0.0'
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/XKCDBrowserApplication.java
View file @
1c6f2322
...
...
@@ -2,6 +2,7 @@ package me.szaki.xkcd.xkcdbrowser;
import
android.app.Application
;
import
me.szaki.xkcd.xkcdbrowser.database.DBModule
;
import
me.szaki.xkcd.xkcdbrowser.ui.UIModule
;
public
class
XKCDBrowserApplication
extends
Application
{
...
...
@@ -10,6 +11,6 @@ public class XKCDBrowserApplication extends Application {
@Override
public
void
onCreate
()
{
super
.
onCreate
();
injector
=
DaggerXKCDBrowserApplicationComponent
.
builder
().
uIModule
(
new
UIModule
(
this
)).
build
();
injector
=
DaggerXKCDBrowserApplicationComponent
.
builder
().
uIModule
(
new
UIModule
(
this
)).
dBModule
(
new
DBModule
(
this
)).
build
();
}
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/XKCDBrowserApplicationComponent.java
View file @
1c6f2322
...
...
@@ -4,15 +4,20 @@ package me.szaki.xkcd.xkcdbrowser;
import
javax.inject.Singleton
;
import
dagger.Component
;
import
me.szaki.xkcd.xkcdbrowser.database.DBModule
;
import
me.szaki.xkcd.xkcdbrowser.interactor.InteractorModule
;
import
me.szaki.xkcd.xkcdbrowser.interactor.comics.ComicsInteractor
;
import
me.szaki.xkcd.xkcdbrowser.network.NetworkModule
;
import
me.szaki.xkcd.xkcdbrowser.ui.UIModule
;
import
me.szaki.xkcd.xkcdbrowser.ui.detail.DetailActivity
;
import
me.szaki.xkcd.xkcdbrowser.ui.detail.DetailPresenter
;
import
me.szaki.xkcd.xkcdbrowser.ui.favorites.FavoritesActivity
;
import
me.szaki.xkcd.xkcdbrowser.ui.favorites.FavoritesPresenter
;
import
me.szaki.xkcd.xkcdbrowser.ui.main.MainActivity
;
import
me.szaki.xkcd.xkcdbrowser.ui.main.MainPresenter
;
@Singleton
@Component
(
modules
=
{
UIModule
.
class
,
InteractorModule
.
class
})
@Component
(
modules
=
{
UIModule
.
class
,
InteractorModule
.
class
,
NetworkModule
.
class
,
DBModule
.
class
})
public
interface
XKCDBrowserApplicationComponent
{
void
inject
(
MainActivity
mainActivity
);
...
...
@@ -21,5 +26,11 @@ public interface XKCDBrowserApplicationComponent {
void
inject
(
FavoritesActivity
favoritesActivity
);
void
inject
(
MainPresenter
mainPresenter
);
void
inject
(
DetailPresenter
detailPresenter
);
void
inject
(
FavoritesPresenter
favoritesPresenter
);
void
inject
(
ComicsInteractor
comicsInteractor
);
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/database/ComicsDAO.java
0 → 100644
View file @
1c6f2322
package
me.szaki.xkcd.xkcdbrowser.database
;
import
android.arch.persistence.room.Dao
;
import
android.arch.persistence.room.Delete
;
import
android.arch.persistence.room.Insert
;
import
android.arch.persistence.room.Query
;
import
android.arch.persistence.room.Update
;
import
java.util.List
;
import
me.szaki.xkcd.xkcdbrowser.model.ComicStrip
;
@Dao
public
interface
ComicsDAO
{
@Query
(
"SELECT * FROM ComicStrip"
)
public
List
<
ComicStrip
>
getAllComics
();
@Query
(
"SELECT * FROM ComicStrip WHERE id = :id"
)
public
ComicStrip
getComic
(
Long
id
);
@Insert
public
void
insertAll
(
ComicStrip
...
comic
);
@Update
public
void
update
(
ComicStrip
comic
);
@Delete
public
void
delete
(
ComicStrip
comic
);
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/database/ComicsDatabase.java
0 → 100644
View file @
1c6f2322
package
me.szaki.xkcd.xkcdbrowser.database
;
import
android.arch.persistence.room.Database
;
import
android.arch.persistence.room.RoomDatabase
;
import
me.szaki.xkcd.xkcdbrowser.model.ComicStrip
;
@Database
(
entities
=
{
ComicStrip
.
class
},
version
=
1
)
public
abstract
class
ComicsDatabase
extends
RoomDatabase
{
public
abstract
ComicsDAO
getDAO
();
}
\ No newline at end of file
app/src/main/java/me/szaki/xkcd/xkcdbrowser/database/DBModule.java
0 → 100644
View file @
1c6f2322
package
me.szaki.xkcd.xkcdbrowser.database
;
import
android.arch.persistence.room.Room
;
import
android.content.Context
;
import
javax.inject.Singleton
;
import
dagger.Module
;
import
dagger.Provides
;
@Module
public
class
DBModule
{
private
Context
context
;
public
DBModule
(
Context
context
)
{
this
.
context
=
context
;
}
@Provides
@Singleton
public
ComicsDatabase
provideComicsDatabase
()
{
return
Room
.
databaseBuilder
(
this
.
context
,
ComicsDatabase
.
class
,
"ComicStrip"
).
build
();
}
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/interactor/InteractorModule.java
View file @
1c6f2322
package
me.szaki.xkcd.xkcdbrowser.interactor
;
import
javax.inject.Singleton
;
import
dagger.Module
;
import
dagger.Provides
;
import
me.szaki.xkcd.xkcdbrowser.interactor.comics.ComicsInteractor
;
import
me.szaki.xkcd.xkcdbrowser.interactor.comics.DBInteractor
;
@Module
public
class
InteractorModule
{
@Singleton
@Provides
public
ComicsInteractor
provideComicsInteractor
()
{
return
new
ComicsInteractor
();
}
@Singleton
@Provides
public
DBInteractor
provideDBInteractor
()
{
return
new
DBInteractor
();
}
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/interactor/comics/ComicsInteractor.java
View file @
1c6f2322
package
me.szaki.xkcd.xkcdbrowser.interactor.comics
;
import
java.io.IOException
;
import
java.util.Date
;
import
java.util.Random
;
import
javax.inject.Inject
;
import
me.szaki.xkcd.xkcdbrowser.XKCDBrowserApplication
;
import
me.szaki.xkcd.xkcdbrowser.network.api.ComicApi
;
import
me.szaki.xkcd.xkcdbrowser.network.model.Comic
;
public
class
ComicsInteractor
{
@Inject
ComicApi
comicApi
;
public
ComicsInteractor
()
{
XKCDBrowserApplication
.
injector
.
inject
(
this
);
}
public
Comic
getComic
(
long
id
)
throws
IOException
{
return
this
.
comicApi
.
getComic
(
id
).
execute
().
body
();
}
public
Comic
getRandomComic
()
throws
IOException
{
Random
r
=
new
Random
(
new
Date
().
getTime
());
return
this
.
comicApi
.
getComic
(
r
.
nextLong
()).
execute
().
body
();
}
public
Comic
getLatestComic
()
throws
IOException
{
return
this
.
comicApi
.
getCurrentComic
().
execute
().
body
();
}
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/interactor/comics/DBInteractor.java
0 → 100644
View file @
1c6f2322
package
me.szaki.xkcd.xkcdbrowser.interactor.comics
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Random
;
import
javax.inject.Inject
;
import
me.szaki.xkcd.xkcdbrowser.database.ComicsDatabase
;
import
me.szaki.xkcd.xkcdbrowser.model.ComicStrip
;
public
class
DBInteractor
{
@Inject
ComicsDatabase
db
;
public
List
<
ComicStrip
>
getComics
()
{
return
db
.
getDAO
().
getAllComics
();
}
public
ComicStrip
getComic
(
Long
id
)
{
return
db
.
getDAO
().
getComic
(
id
);
}
public
void
deleteComic
(
ComicStrip
c
)
{
db
.
getDAO
().
delete
(
c
);
}
public
void
saveComic
(
ComicStrip
c
)
{
db
.
getDAO
().
insertAll
(
c
);
}
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/model/ComicStrip.java
0 → 100644
View file @
1c6f2322
package
me.szaki.xkcd.xkcdbrowser.model
;
import
android.arch.persistence.room.Entity
;
import
android.arch.persistence.room.PrimaryKey
;
@Entity
public
class
ComicStrip
{
@PrimaryKey
(
autoGenerate
=
true
)
int
id
;
String
month
;
Long
num
;
String
link
;
String
year
;
String
news
;
String
safe_title
;
String
transcript
;
String
alt
;
String
img
;
String
title
;
String
day
;
public
int
getId
()
{
return
id
;
}
public
void
setId
(
int
id
)
{
this
.
id
=
id
;
}
public
String
getMonth
()
{
return
month
;
}
public
void
setMonth
(
String
month
)
{
this
.
month
=
month
;
}
public
Long
getNum
()
{
return
num
;
}
public
void
setNum
(
Long
num
)
{
this
.
num
=
num
;
}
public
String
getLink
()
{
return
link
;
}
public
void
setLink
(
String
link
)
{
this
.
link
=
link
;
}
public
String
getYear
()
{
return
year
;
}
public
void
setYear
(
String
year
)
{
this
.
year
=
year
;
}
public
String
getNews
()
{
return
news
;
}
public
void
setNews
(
String
news
)
{
this
.
news
=
news
;
}
public
String
getSafe_title
()
{
return
safe_title
;
}
public
void
setSafe_title
(
String
safe_title
)
{
this
.
safe_title
=
safe_title
;
}
public
String
getTranscript
()
{
return
transcript
;
}
public
void
setTranscript
(
String
transcript
)
{
this
.
transcript
=
transcript
;
}
public
String
getAlt
()
{
return
alt
;
}
public
void
setAlt
(
String
alt
)
{
this
.
alt
=
alt
;
}
public
String
getImg
()
{
return
img
;
}
public
void
setImg
(
String
img
)
{
this
.
img
=
img
;
}
public
String
getTitle
()
{
return
title
;
}
public
void
setTitle
(
String
title
)
{
this
.
title
=
title
;
}
public
String
getDay
()
{
return
day
;
}
public
void
setDay
(
String
day
)
{
this
.
day
=
day
;
}
}
app/src/main/java/me/szaki/xkcd/xkcdbrowser/network/ApiClient.java
0 → 100644
View file @
1c6f2322
package
me.szaki.xkcd.xkcdbrowser.network
;
import
java.io.IOException
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.Type
;
import
java.util.Date
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
import
org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder
;
import
org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder
;
import
retrofit2.Converter
;
import
retrofit2.Retrofit
;
import
retrofit2.GsonConverterFactory
;
import
com.google.gson.Gson
;
import
com.google.gson.GsonBuilder
;
import
com.google.gson.JsonParseException
;
import
okhttp3.Interceptor
;
import
okhttp3.OkHttpClient
;
import
okhttp3.RequestBody
;
import
okhttp3.ResponseBody
;
import
me.szaki.xkcd.xkcdbrowser.network.auth.HttpBasicAuth
;
import
me.szaki.xkcd.xkcdbrowser.network.auth.ApiKeyAuth
;
import
me.szaki.xkcd.xkcdbrowser.network.auth.OAuth
;
import
me.szaki.xkcd.xkcdbrowser.network.auth.OAuth.AccessTokenListener
;
import
me.szaki.xkcd.xkcdbrowser.network.auth.OAuthFlow
;
public
class
ApiClient
{
private
Map
<
String
,
Interceptor
>
apiAuthorizations
;
private
OkHttpClient
okClient
;
private
Retrofit
.
Builder
adapterBuilder
;
public
ApiClient
()
{
apiAuthorizations
=
new
LinkedHashMap
<
String
,
Interceptor
>();
createDefaultAdapter
();
}
public
ApiClient
(
String
[]
authNames
)
{
this
();
for
(
String
authName
:
authNames
)
{
throw
new
RuntimeException
(
"auth name \""
+
authName
+
"\" not found in available auth names"
);
}
}
/**
* Basic constructor for single auth name
* @param authName
*/
public
ApiClient
(
String
authName
)
{
this
(
new
String
[]{
authName
});
}
/**
* Helper constructor for single api key
* @param authName
* @param apiKey
*/
public
ApiClient
(
String
authName
,
String
apiKey
)
{
this
(
authName
);
this
.
setApiKey
(
apiKey
);
}
/**
* Helper constructor for single basic auth or password oauth2
* @param authName
* @param username
* @param password
*/
public
ApiClient
(
String
authName
,
String
username
,
String
password
)
{
this
(
authName
);
this
.
setCredentials
(
username
,
password
);
}
/**
* Helper constructor for single password oauth2
* @param authName
* @param clientId
* @param secret
* @param username
* @param password
*/
public
ApiClient
(
String
authName
,
String
clientId
,
String
secret
,
String
username
,
String
password
)
{
this
(
authName
);
this
.
getTokenEndPoint
()
.
setClientId
(
clientId
)
.
setClientSecret
(
secret
)
.
setUsername
(
username
)
.
setPassword
(
password
);
}
public
void
createDefaultAdapter
()
{
Gson
gson
=
new
GsonBuilder
()
.
setDateFormat
(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ"
)
.
create
();
okClient
=
new
OkHttpClient
();
String
baseUrl
=
"https://xkcd.com/"
;
if
(!
baseUrl
.
endsWith
(
"/"
))
baseUrl
=
baseUrl
+
"/"
;
adapterBuilder
=
new
Retrofit
.
Builder
()
.
baseUrl
(
baseUrl
)
.
client
(
okClient
)
.
addConverterFactory
(
GsonCustomConverterFactory
.
create
(
gson
));
}
public
<
S
>
S
createService
(
Class
<
S
>
serviceClass
)
{
return
adapterBuilder
.
build
().
create
(
serviceClass
);
}
/**
* Helper method to configure the first api key found
* @param apiKey
*/
private
void
setApiKey
(
String
apiKey
)
{
for
(
Interceptor
apiAuthorization
:
apiAuthorizations
.
values
())
{
if
(
apiAuthorization
instanceof
ApiKeyAuth
)
{
ApiKeyAuth
keyAuth
=
(
ApiKeyAuth
)
apiAuthorization
;
keyAuth
.
setApiKey
(
apiKey
);
return
;
}
}
}
/**
* Helper method to configure the username/password for basic auth or password oauth
* @param username
* @param password
*/
private
void
setCredentials
(
String
username
,
String
password
)
{
for
(
Interceptor
apiAuthorization
:
apiAuthorizations
.
values
())
{
if
(
apiAuthorization
instanceof
HttpBasicAuth
)
{
HttpBasicAuth
basicAuth
=
(
HttpBasicAuth
)
apiAuthorization
;
basicAuth
.
setCredentials
(
username
,
password
);
return
;
}
if
(
apiAuthorization
instanceof
OAuth
)
{
OAuth
oauth
=
(
OAuth
)
apiAuthorization
;
oauth
.
getTokenRequestBuilder
().
setUsername
(
username
).
setPassword
(
password
);
return
;
}
}
}
/**
* Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one)
* @return
*/
public
TokenRequestBuilder
getTokenEndPoint
()
{
for
(
Interceptor
apiAuthorization
:
apiAuthorizations
.
values
())
{
if
(
apiAuthorization
instanceof
OAuth
)
{
OAuth
oauth
=
(
OAuth
)
apiAuthorization
;
return
oauth
.
getTokenRequestBuilder
();
}
}
return
null
;
}
/**
* Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one)
* @return
*/
public
AuthenticationRequestBuilder
getAuthorizationEndPoint
()
{
for
(
Interceptor
apiAuthorization
:
apiAuthorizations
.
values
())
{
if
(
apiAuthorization
instanceof
OAuth
)
{
OAuth
oauth
=
(
OAuth
)
apiAuthorization
;
return
oauth
.
getAuthenticationRequestBuilder
();
}
}
return
null
;
}
/**
* Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one)
* @param accessToken
*/
public
void
setAccessToken
(
String
accessToken
)
{
for
(
Interceptor
apiAuthorization
:
apiAuthorizations
.
values
())
{
if
(
apiAuthorization
instanceof
OAuth
)
{
OAuth
oauth
=
(
OAuth
)
apiAuthorization
;
oauth
.
setAccessToken
(
accessToken
);
return
;
}
}
}
/**
* Helper method to configure the oauth accessCode/implicit flow parameters
* @param clientId