Unverified Commit 1c6f2322 authored by Tamás Szabó's avatar Tamás Szabó Committed by GitHub
Browse files

Merge pull request #9 from szakitom/development

labor5
parents 314db438 445eb50e
......@@ -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">
......
......@@ -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'
}
......@@ -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();
}
}
......@@ -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);
}
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);
}
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
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();
}
}
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();
}
}
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();
}
}
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);
}
}
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;
}
}
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